Fixed problem with UEFI iSCSI boot for adapters

This commit fixes problem with multiple nic adapter
by adding mac as an optional parameter to pass macs in
such cases.

Change-Id: Iea420d7a047c8ac849fa2eeab5c6892be2d7a6e1
Bug-Id: 1838730
This commit is contained in:
paresh-sao 2019-07-19 08:25:52 +00:00 committed by kesper
parent 3a71f3b5d4
commit 94d4e1c372
13 changed files with 634 additions and 178 deletions

View File

@ -62,9 +62,7 @@ SUPPORTED_RIS_METHODS = [
'set_one_time_boot',
'set_pending_boot_mode',
'set_secure_boot_mode',
'set_iscsi_boot_info',
'set_iscsi_info',
'unset_iscsi_boot_info',
'unset_iscsi_info',
'get_iscsi_initiator_info',
'set_iscsi_initiator_info',
@ -114,9 +112,7 @@ SUPPORTED_REDFISH_METHODS = [
'get_server_capabilities',
'get_supported_boot_mode',
'get_essential_properties',
'set_iscsi_boot_info',
'set_iscsi_info',
'unset_iscsi_boot_info',
'unset_iscsi_info',
'get_iscsi_initiator_info',
'set_iscsi_initiator_info'
@ -372,7 +368,7 @@ class IloClient(operations.IloOperations):
def set_iscsi_info(self, target_name, lun, ip_address,
port='3260', auth_method=None, username=None,
password=None):
password=None, macs=[]):
"""Set iscsi details of the system in uefi boot mode.
The initiator system is set with the target details like
@ -384,60 +380,24 @@ class IloClient(operations.IloOperations):
:param auth_method : either None or CHAP.
:param username: CHAP Username for authentication.
:param password: CHAP secret.
:param mac: List of target mac for iSCSI.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the bios boot mode.
"""
return self._call_method('set_iscsi_info', target_name, lun,
ip_address, port, auth_method, username,
password)
password, macs)
def set_iscsi_boot_info(self, mac, target_name, lun, ip_address,
port='3260', auth_method=None, username=None,
password=None):
"""Set iscsi details of the system in uefi boot mode.
The initiator system is set with the target details like
IQN, LUN, IP, Port etc.
:param mac: The MAC of the NIC to be set with iSCSI information
:param target_name: Target Name for iscsi.
:param lun: logical unit number.
:param ip_address: IP address of the target.
:param port: port of the target.
:param auth_method : either None or CHAP.
:param username: CHAP Username for authentication.
:param password: CHAP secret.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the bios boot mode.
"""
LOG.warning("'set_iscsi_boot_info' is deprecated. The 'MAC' parameter"
"passed in is ignored. Use 'set_iscsi_info' instead.")
return self._call_method('set_iscsi_info', target_name, lun,
ip_address, port, auth_method, username,
password)
def unset_iscsi_info(self):
def unset_iscsi_info(self, macs=[]):
"""Disable iscsi boot option of the system in uefi boot mode.
:param mac: List of target mac for iSCSI.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the bios boot mode.
"""
return self._call_method('unset_iscsi_info')
def unset_iscsi_boot_info(self, mac):
"""Disable iscsi boot option of the system in uefi boot mode.
:param mac: The MAC of the NIC to be set with iSCSI information.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the bios boot mode.
"""
LOG.warning("'unset_iscsi_boot_info' is deprecated. The 'MAC' "
"parameter passed in is ignored. Use 'unset_iscsi_info' "
"instead.")
return self._call_method('unset_iscsi_info')
return self._call_method('unset_iscsi_info', macs)
def get_iscsi_initiator_info(self):
"""Returns iSCSI initiator information of iLO.

View File

@ -66,7 +66,7 @@ class IloOperations(object):
def set_iscsi_info(self, target_name, lun, ip_address,
port='3260', auth_method=None, username=None,
password=None):
password=None, macs=[]):
"""Set iscsi details of the system in uefi boot mode.
The initiator system is set with the target details like
@ -78,15 +78,17 @@ class IloOperations(object):
:param auth_method : either None or CHAP.
:param username: CHAP Username for authentication.
:param password: CHAP secret.
:param mac: List of target macs for iSCSI.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the bios boot mode.
"""
raise exception.IloCommandNotSupportedError(ERRMSG)
def unset_iscsi_info(self):
def unset_iscsi_info(self, macs=[]):
"""Disable iscsi boot option of the system in uefi boot mode.
:param mac: List of target macs for iSCSI.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the system is
in the bios boot mode.

View File

@ -604,40 +604,104 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
' does not exist')
raise exception.IloCommandNotSupportedError(msg)
def _change_iscsi_settings(self, iscsi_info):
def _get_uefi_device_path_by_mac(self, mac):
"""Return uefi device path of mac.
:returns: Uefi Device path.
Ex. 'PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)'
"""
adapter_uri = '/rest/v1/Systems/1/NetworkAdapters'
for status, headers, member, memberuri in (
self._get_collection(adapter_uri)):
if status < 300 and member.get('PhysicalPorts'):
for port in member.get('PhysicalPorts'):
if port['MacAddress'].lower() == mac.lower():
return port['UEFIDevicePath']
def _get_nic_association_name_by_mac(self, mac):
"""Return nic association name by mac address
:returns: Nic association name. Ex. NicBoot1
"""
headers, bios_uri, bios_settings = self._check_bios_resource()
mappings = (
self._get_bios_mappings_resource(
bios_settings).get('BiosPciSettingsMappings'))
correlatable_id = self._get_uefi_device_path_by_mac(mac)
for mapping in mappings:
for subinstance in mapping['Subinstances']:
for association in subinstance['Associations']:
if subinstance.get('CorrelatableID') == correlatable_id:
return [name for name in subinstance[
'Associations'] if 'NicBoot' in name][0]
def _get_all_macs(self):
"""Return list of macs available on system
:returns: List of macs
"""
macs = []
adapter_uri = '/rest/v1/Systems/1/NetworkAdapters'
for status, headers, member, memberuri in (
self._get_collection(adapter_uri)):
if status < 300 and member.get('PhysicalPorts'):
for port in member.get('PhysicalPorts'):
macs.append(port['MacAddress'].lower())
return macs
def _validate_macs(self, macs):
"""Validate given macs are there in system
:param macs: List of macs
:raises: InvalidInputError, if macs not valid
"""
macs_available = self._get_all_macs()
if not set(macs).issubset(macs_available):
msg = ("Given macs: %(macs)s not found in the system"
% {'macs': str(macs)})
raise exception.InvalidInputError(msg)
def _change_iscsi_settings(self, iscsi_info, macs=[]):
"""Change iSCSI settings.
:param macs: List of target macs for iSCSI.
:param iscsi_info: A dictionary that contains information of iSCSI
target like target_name, lun, ip_address, port etc.
:raises: IloError, on an error from iLO.
"""
headers, bios_uri, bios_settings = self._check_bios_resource()
# Get the Mappings resource.
map_settings = self._get_bios_mappings_resource(bios_settings)
nics = []
for mapping in map_settings['BiosPciSettingsMappings']:
for subinstance in mapping['Subinstances']:
for association in subinstance['Associations']:
if 'NicBoot' in association:
nics.append(association)
iscsi_uri = self._check_iscsi_rest_patch_allowed()
association_names = []
if macs:
self._validate_macs(macs)
association_names = [
self._get_nic_association_name_by_mac(mac) for mac in macs]
else:
# Get the Mappings resource.
headers, bios_uri, bios_settings = self._check_bios_resource()
map_settings = self._get_bios_mappings_resource(bios_settings)
for mapping in map_settings['BiosPciSettingsMappings']:
for subinstance in mapping['Subinstances']:
for association in subinstance['Associations']:
if 'NicBoot' in association:
association_names.append(association)
if not nics:
msg = ('No nics found')
if not association_names:
msg = ('No macs were found on the system')
raise exception.IloError(msg)
iscsi_uri = self._check_iscsi_rest_patch_allowed()
# Set iSCSI info to all nics
iscsi_infos = []
for nic in nics:
for association_name in association_names:
data = iscsi_info.copy()
data['iSCSIBootAttemptName'] = nic
data['iSCSINicSource'] = nic
data['iSCSIBootAttemptInstance'] = nics.index(nic) + 1
data['iSCSIBootAttemptName'] = association_name
data['iSCSINicSource'] = association_name
data['iSCSIBootAttemptInstance'] = (
association_names.index(association_name) + 1)
iscsi_infos.append(data)
patch_data = {'iSCSIBootSources': iscsi_infos}
iscsi_data = {'iSCSIBootSources': iscsi_infos}
status, headers, response = self._rest_patch(iscsi_uri,
None, patch_data)
None, iscsi_data)
if status >= 300:
msg = self._get_extended_error(response)
raise exception.IloError(msg)
@ -914,7 +978,7 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
def set_iscsi_info(self, target_name, lun, ip_address,
port='3260', auth_method=None, username=None,
password=None):
password=None, macs=[]):
"""Set iSCSI details of the system in UEFI boot mode.
The initiator system is set with the target details like
@ -926,6 +990,7 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
:param auth_method : either None or CHAP.
:param username: CHAP Username for authentication.
:param password: CHAP secret.
:param macs: List of target macs for iSCSI.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the BIOS boot mode.
@ -942,21 +1007,22 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
iscsi_info['iSCSIAuthenticationMethod'] = 'Chap'
iscsi_info['iSCSIChapUsername'] = username
iscsi_info['iSCSIChapSecret'] = password
self._change_iscsi_settings(iscsi_info)
self._change_iscsi_settings(iscsi_info, macs)
else:
msg = 'iSCSI boot is not supported in the BIOS boot mode'
raise exception.IloCommandNotSupportedInBiosError(msg)
def unset_iscsi_info(self):
def unset_iscsi_info(self, macs=[]):
"""Disable iSCSI boot option in UEFI boot mode.
:param macs: List of target macs for iSCSI.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the BIOS boot mode.
"""
if(self._is_boot_mode_uefi() is True):
iscsi_info = {'iSCSIBootEnable': 'Disabled'}
self._change_iscsi_settings(iscsi_info)
self._change_iscsi_settings(iscsi_info, macs)
else:
msg = 'iSCSI boot is not supported in the BIOS boot mode'
raise exception.IloCommandNotSupportedInBiosError(msg)

View File

@ -884,23 +884,47 @@ class RedfishOperations(operations.IloOperations):
LOG.debug(msg)
raise exception.IloError(msg)
def _change_iscsi_target_settings(self, iscsi_info):
def _change_iscsi_target_settings(self, iscsi_info, macs=[]):
"""Change iSCSI target settings.
:param macs: List of target mac for iSCSI.
:param iscsi_info: A dictionary that contains information of iSCSI
target like target_name, lun, ip_address, port etc.
:raises: IloError, on an error from iLO.
"""
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
association_names = []
try:
pci_settings_map = (
sushy_system.bios_settings.bios_mappings.pci_settings_mappings)
nics = []
for mapping in pci_settings_map:
for subinstance in mapping['Subinstances']:
for association in subinstance['Associations']:
if 'NicBoot' in association:
nics.append(association)
if macs:
sushy_system.validate_macs(macs)
association_names = [
sushy_system.get_nic_association_name_by_mac(
mac) for mac in macs]
else:
pci_settings_map = (
sushy_system.bios_settings.
bios_mappings.pci_settings_mappings)
for mapping in pci_settings_map:
for subinstance in mapping['Subinstances']:
for association in subinstance['Associations']:
if 'NicBoot' in association:
association_names.append(association)
if not association_names:
msg = ('No macs were found on the system')
raise exception.IloError(msg)
# Set iSCSI info to all nics
iscsi_infos = []
for association_name in association_names:
data = iscsi_info.copy()
data['iSCSIAttemptName'] = association_name
data['iSCSINicSource'] = association_name
data['iSCSIAttemptInstance'] = (
association_names.index(association_name) + 1)
iscsi_infos.append(data)
iscsi_data = {'iSCSISources': iscsi_infos}
except sushy.exceptions.SushyError as e:
msg = (self._('The Redfish controller failed to get the '
'bios mappings. Error %(error)s')
@ -908,20 +932,6 @@ class RedfishOperations(operations.IloOperations):
LOG.debug(msg)
raise exception.IloError(msg)
if not nics:
msg = ('No nics were found on the system')
raise exception.IloError(msg)
# Set iSCSI info to all nics
iscsi_infos = []
for nic in nics:
data = iscsi_info.copy()
data['iSCSIAttemptName'] = nic
data['iSCSINicSource'] = nic
data['iSCSIAttemptInstance'] = nics.index(nic) + 1
iscsi_infos.append(data)
iscsi_data = {'iSCSISources': iscsi_infos}
try:
(sushy_system.bios_settings.iscsi_resource.
iscsi_settings.update_iscsi_settings(iscsi_data))
@ -934,7 +944,7 @@ class RedfishOperations(operations.IloOperations):
def set_iscsi_info(self, target_name, lun, ip_address,
port='3260', auth_method=None, username=None,
password=None):
password=None, macs=[]):
"""Set iSCSI details of the system in UEFI boot mode.
The initiator system is set with the target details like
@ -946,6 +956,7 @@ class RedfishOperations(operations.IloOperations):
:param auth_method : either None or CHAP.
:param username: CHAP Username for authentication.
:param password: CHAP secret.
:param macs: List of target macs for iSCSI.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the bios boot mode.
"""
@ -961,20 +972,21 @@ class RedfishOperations(operations.IloOperations):
iscsi_info['iSCSIAuthenticationMethod'] = 'Chap'
iscsi_info['iSCSIChapUsername'] = username
iscsi_info['iSCSIChapSecret'] = password
self._change_iscsi_target_settings(iscsi_info)
self._change_iscsi_target_settings(iscsi_info, macs)
else:
msg = 'iSCSI boot is not supported in the BIOS boot mode'
raise exception.IloCommandNotSupportedInBiosError(msg)
def unset_iscsi_info(self):
def unset_iscsi_info(self, macs=[]):
"""Disable iSCSI boot option in UEFI boot mode.
:param macs: List of target macs for iSCSI.
:raises: IloCommandNotSupportedInBiosError, if the system is
in the BIOS boot mode.
"""
if(self._is_boot_mode_uefi()):
iscsi_info = {'iSCSIConnection': 'Disabled'}
self._change_iscsi_target_settings(iscsi_info)
self._change_iscsi_target_settings(iscsi_info, macs)
else:
msg = 'iSCSI boot is not supported in the BIOS boot mode'
raise exception.IloCommandNotSupportedInBiosError(msg)

View File

@ -22,7 +22,9 @@ from sushy import utils as sushy_utils
from proliantutils.redfish.resources.system import constants as sys_cons
EthernetInterface = ethernet_interface.EthernetInterface
class EthernetInterface(ethernet_interface.EthernetInterface):
uefi_device_path = base.Field('UefiDevicePath')
class EthernetInterfaceCollection(base.ResourceCollectionBase):
@ -54,3 +56,16 @@ class EthernetInterfaceCollection(base.ResourceCollectionBase):
mac_dict.update(
{'Port ' + eth.identity: eth.mac_address})
return mac_dict
def get_uefi_device_path_by_mac(self, mac):
"""Return uefi device path of mac"""
for nic in self.get_members():
if nic.mac_address.lower() == mac.lower():
return nic.uefi_device_path
def get_all_macs(self):
"""Return list of macs available on system"""
macs = []
for mac in self.get_members():
macs.append(mac.mac_address.lower())
return macs

View File

@ -627,3 +627,30 @@ class HPESystem(system.System):
'Error: %(error)s'
% {'error': str(e)})
raise exception.IloError(msg)
def validate_macs(self, macs):
"""Validate given macs are there in system
:param macs: List of macs
:raises: InvalidInputError, if macs not valid
"""
macs_available = self.ethernet_interfaces.get_all_macs()
if not set(macs).issubset(macs_available):
msg = ("Given macs: %(macs)s not found in the system"
% {'macs': str(macs)})
raise exception.InvalidInputError(msg)
def get_nic_association_name_by_mac(self, mac):
"""Return nic association name by mac address
:returns: Nic association name. Ex. NicBoot1
"""
mappings = self.bios_settings.bios_mappings.pci_settings_mappings
correlatable_id = self.ethernet_interfaces.get_uefi_device_path_by_mac(
mac)
for mapping in mappings:
for subinstance in mapping['Subinstances']:
for association in subinstance['Associations']:
if subinstance.get('CorrelatableID') == correlatable_id:
return [name for name in subinstance[
'Associations'] if 'NicBoot' in name][0]

View File

@ -1270,6 +1270,71 @@ GET_MANAGER_DETAILS_NO_FIRMWARE = """
}
"""
RESP_NETWORK_ADAPTER = """
{
"@odata.context": "/redfish/v1/$metadata#Systems/Members/1/\
NetworkAdapters/Members/$entity",
"@odata.id": "/redfish/v1/Systems/1/NetworkAdapters/1/",
"@odata.type": "#BaseNetworkAdapter.1.1.0.BaseNetworkAdapter",
"Firmware": {
"Current": {
"VersionString": null
}
},
"Id": "1",
"Name": "HPE Ethernet 1Gb 2-port 361i Adapter - NIC",
"PartNumber": null,
"PhysicalPorts": [
{
"FullDuplex": false,
"IPv4Addresses": [
{
"Address": null
}
],
"IPv6Addresses": [
{
"Address": null
}
],
"MacAddress": "9C:B6:54:79:78:70",
"Name": null,
"Oem": {
"Hp": {
"@odata.type": "#HpBaseNetworkAdapterExt.1.0.0.\
HpBaseNetworkAdapterExt",
"BadReceives": null,
"BadTransmits": null,
"GoodReceives": null,
"GoodTransmits": null,
"StructuredName": "NIC.LOM.1.1",
"Team": null,
"Type": "HpBaseNetworkAdapterExt.1.0.0"
}
},
"SpeedMbps": 0,
"Status": {
"Health": "OK",
"State": "Enabled"
},
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)"
}
],
"SerialNumber": null,
"Status": {
"Health": "OK",
"State": "Enabled"
},
"StructuredName": "NIC.LOM.1.1",
"Type": "BaseNetworkAdapter.1.1.0",
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)",
"links": {
"self": {
"href": "/rest/v1/Systems/1/NetworkAdapters/1"
}
}
}
"""
GET_BIOS_SETTINGS = """
{
@ -2536,7 +2601,7 @@ GET_ISCSI_PATCH = """
"iSCSITargetName": "iqn.2011-07.com.example.server:test1",
"iSCSITargetTcpPort": 3260
}
]
]
}
"""

View File

@ -518,18 +518,7 @@ class IloClientTestCase(testtools.TestCase):
call_mock.assert_called_once_with('set_iscsi_info',
'iqn.2011-07.com:example:123',
'1', '10.10.1.23', '3260',
'CHAP', 'user', 'password')
@mock.patch.object(client.IloClient.cls, '_call_method')
def test_set_iscsi_boot_info(self, call_mock):
self.client.set_iscsi_boot_info('aa:bb:cc:dd:ee:ff',
'iqn.2011-07.com:example:123',
'1', '10.10.1.23', '3260', 'CHAP',
'user', 'password')
call_mock.assert_called_once_with('set_iscsi_info',
'iqn.2011-07.com:example:123',
'1', '10.10.1.23', '3260',
'CHAP', 'user', 'password')
'CHAP', 'user', 'password', [])
@mock.patch.object(client.IloClient.cls, '_call_method')
def test_get_iscsi_initiator_info(self, call_mock):
@ -539,12 +528,7 @@ class IloClientTestCase(testtools.TestCase):
@mock.patch.object(client.IloClient.cls, '_call_method')
def test_unset_iscsi_info(self, call_mock):
self.client.unset_iscsi_info()
call_mock.assert_called_once_with('unset_iscsi_info')
@mock.patch.object(client.IloClient.cls, '_call_method')
def test_unset_iscsi_boot_info(self, call_mock):
self.client.unset_iscsi_boot_info("aa:bb:cc:dd:ee:ff")
call_mock.assert_called_once_with('unset_iscsi_info')
call_mock.assert_called_once_with('unset_iscsi_info', [])
@mock.patch.object(client.IloClient.cls, '_call_method')
def test_set_iscsi_initiator_info(self, call_mock):

View File

@ -160,7 +160,27 @@ class IloRisTestCase(testtools.TestCase):
'iqn.2011-07.com.example.server:test1',
'1', '10.10.1.30')
_uefi_boot_mode_mock.assert_called_once_with()
change_iscsi_settings_mock.assert_called_once_with(iscsi_variables)
change_iscsi_settings_mock.assert_called_once_with(
iscsi_variables, [])
@mock.patch.object(ris.RISOperations, '_change_iscsi_settings')
@mock.patch.object(ris.RISOperations, '_is_boot_mode_uefi')
def test_set_iscsi_info_uefi_with_mac(self, _uefi_boot_mode_mock,
change_iscsi_settings_mock):
_uefi_boot_mode_mock.return_value = True
iscsi_variables = {
'iSCSITargetName': 'iqn.2011-07.com.example.server:test1',
'iSCSITargetInfoViaDHCP': False,
'iSCSIBootLUN': '1',
'iSCSIBootEnable': 'Enabled',
'iSCSITargetIpAddress': '10.10.1.30',
'iSCSITargetTcpPort': 3260}
self.client.set_iscsi_info(
'iqn.2011-07.com.example.server:test1',
'1', '10.10.1.30', macs=['98:f2:b3:ee:f4:00'])
_uefi_boot_mode_mock.assert_called_once_with()
change_iscsi_settings_mock.assert_called_once_with(
iscsi_variables, ['98:f2:b3:ee:f4:00'])
@mock.patch.object(ris.RISOperations, '_change_iscsi_settings')
@mock.patch.object(ris.RISOperations, '_is_boot_mode_uefi')
@ -170,7 +190,19 @@ class IloRisTestCase(testtools.TestCase):
iscsi_variables = {'iSCSIBootEnable': 'Disabled'}
self.client.unset_iscsi_info()
_uefi_boot_mode_mock.assert_called_once_with()
change_iscsi_settings_mock.assert_called_once_with(iscsi_variables)
change_iscsi_settings_mock.assert_called_once_with(
iscsi_variables, [])
@mock.patch.object(ris.RISOperations, '_change_iscsi_settings')
@mock.patch.object(ris.RISOperations, '_is_boot_mode_uefi')
def test_unset_iscsi_info_uefi_with_mac(self, _uefi_boot_mode_mock,
change_iscsi_settings_mock):
_uefi_boot_mode_mock.return_value = True
iscsi_variables = {'iSCSIBootEnable': 'Disabled'}
self.client.unset_iscsi_info(['98:f2:b3:ee:f4:00'])
_uefi_boot_mode_mock.assert_called_once_with()
change_iscsi_settings_mock.assert_called_once_with(
iscsi_variables, ['98:f2:b3:ee:f4:00'])
@mock.patch.object(ris.RISOperations, '_is_boot_mode_uefi')
def test_unset_iscsi_info_bios(self, _uefi_boot_mode_mock):
@ -1736,6 +1768,57 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
self.client._check_iscsi_rest_patch_allowed)
check_bios_mock.assert_called_once_with()
@mock.patch.object(ris.RISOperations, '_get_uefi_device_path_by_mac')
@mock.patch.object(ris.RISOperations, '_get_bios_mappings_resource')
@mock.patch.object(ris.RISOperations, '_check_bios_resource')
def test__get_nic_association_name_by_mac(
self, check_bios_mock, mappings_mock, uefi_device_path_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)
map_settings = json.loads(ris_outputs.GET_BIOS_MAPPINGS)
mappings_mock.return_value = map_settings
(uefi_device_path_mock.
return_value) = 'PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)'
result = (
self.client._get_nic_association_name_by_mac('98:f2:b3:ee:f4:00'))
self.assertEqual(result, 'NicBoot1')
@mock.patch.object(ris.RISOperations, '_get_collection')
def test__get_all_macs(self, collection_mock):
member_uri = '/rest/v1/Systems/1/NetworkAdapters'
collection_item = json.loads(ris_outputs.RESP_NETWORK_ADAPTER)
collection_mock.return_value = [(200, None, collection_item,
member_uri)]
result = self.client._get_all_macs()
self.assertEqual(result, ['9c:b6:54:79:78:70'])
@mock.patch.object(ris.RISOperations, '_get_all_macs')
def test__validate_macs(self, get_all_macs_mock):
get_all_macs_mock.return_value = [
'12:44:6a:3b:04:11', '13:44:6a:3b:04:13']
result = self.client._validate_macs(['12:44:6a:3b:04:11'])
self.assertEqual(result, None)
@mock.patch.object(ris.RISOperations, '_get_all_macs')
def test_validate_macs_failed(self, get_all_macs_mock):
get_all_macs_mock.return_value = [
'12:44:6a:3b:04:11', '13:44:6a:3b:04:13']
self.assertRaisesRegex(
exception.InvalidInputError,
"Given macs: \['12:44:6A:3B:04:15'\] not found in the system",
self.client._validate_macs, ['12:44:6A:3B:04:15'])
@mock.patch.object(ris.RISOperations, '_get_collection')
def test__get_uefi_device_path_by_mac(self, collection_mock):
member_uri = '/rest/v1/Systems/1/NetworkAdapters'
collection_item = json.loads(ris_outputs.RESP_NETWORK_ADAPTER)
collection_mock.return_value = [(200, None, collection_item,
member_uri)]
result = self.client._get_uefi_device_path_by_mac('9c:b6:54:79:78:70')
self.assertEqual(result, 'PciRoot(0x0)/Pci(0x2,0x3)/Pci(0x0,0x0)')
@mock.patch.object(ris.RISOperations, '_rest_patch')
@mock.patch.object(ris.RISOperations, '_check_iscsi_rest_patch_allowed')
@mock.patch.object(ris.RISOperations, '_get_bios_mappings_resource')
@ -1759,25 +1842,66 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
check_iscsi_mock.return_value = iscsi_uri
patch_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client._change_iscsi_settings(properties)
self.client._change_iscsi_settings(properties, [])
check_bios_mock.assert_called_once_with()
mappings_mock.assert_called_once_with(bios_settings)
check_iscsi_mock.assert_called_once_with()
patch_mock.assert_called_once_with(iscsi_uri, None, settings)
@mock.patch.object(ris.RISOperations, '_validate_macs')
@mock.patch.object(ris.RISOperations, '_get_nic_association_name_by_mac')
@mock.patch.object(ris.RISOperations, '_rest_patch')
@mock.patch.object(ris.RISOperations, '_check_iscsi_rest_patch_allowed')
def test__change_iscsi_settings_with_mac(
self, check_iscsi_mock, patch_mock, nic_association_mock,
validate_mock):
nic_association_mock.return_value = 'NicBoot1'
iscsi_uri = '/rest/v1/systems/1/bios/iScsi/Settings'
properties = {'iSCSITargetName':
'iqn.2011-07.com.example.server:test1',
'iSCSIBootLUN': '1',
'iSCSITargetIpAddress': '10.10.1.30',
'iSCSITargetTcpPort': 3260}
settings = json.loads(ris_outputs.GET_ISCSI_PATCH)
check_iscsi_mock.return_value = iscsi_uri
patch_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client._change_iscsi_settings(properties, ['98:f2:b3:ee:f4:00'])
patch_mock.assert_called_once_with(
iscsi_uri, None,
{'iSCSIBootSources': [settings['iSCSIBootSources'][0]]})
validate_mock.assert_called_once_with(['98:f2:b3:ee:f4:00'])
@mock.patch.object(ris.RISOperations, '_validate_macs')
@mock.patch.object(ris.RISOperations, '_check_iscsi_rest_patch_allowed')
def test__change_iscsi_settings_invalid_mac(
self, check_iscsi_mock, validate_macs_mock):
iscsi_uri = '/rest/v1/systems/1/bios/iScsi/Settings'
check_iscsi_mock.return_value = iscsi_uri
msg = ("Given macs: %(macs)s not found in the system"
% {'macs': str(['12:44:6A:3B:04:15'])})
validate_macs_mock.side_effect = exception.InvalidInputError(msg)
self.assertRaisesRegex(
exception.InvalidInputError,
"Given macs: \['12:44:6A:3B:04:15'\] not found in the system",
self.client._change_iscsi_settings, {}, ['12:44:6A:3B:04:15'])
@mock.patch.object(ris.RISOperations, '_check_iscsi_rest_patch_allowed')
@mock.patch.object(ris.RISOperations, '_get_bios_mappings_resource')
@mock.patch.object(ris.RISOperations, '_check_bios_resource')
def test__change_iscsi_settings_without_nic(self, check_bios_mock,
mappings_mock):
def test__change_iscsi_settings_no_macs(
self, check_bios_mock, mappings_mock, check_iscsi_mock):
bios_uri = '/rest/v1/systems/1/bios'
iscsi_uri = '/rest/v1/systems/1/bios/iScsi/Settings'
bios_settings = json.loads(ris_outputs.GET_BIOS_SETTINGS)
check_bios_mock.return_value = (ris_outputs.GET_HEADERS,
bios_uri, bios_settings)
map_settings = json.loads(ris_outputs.GET_BIOS_MAPPINGS_WITHOUT_NIC)
mappings_mock.return_value = map_settings
check_iscsi_mock.return_value = iscsi_uri
self.assertRaises(exception.IloError,
self.client._change_iscsi_settings,
{})
self.client._change_iscsi_settings, {},
[])
check_bios_mock.assert_called_once_with()
mappings_mock.assert_called_once_with(bios_settings)
@ -1806,7 +1930,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
ris_outputs.REST_POST_RESPONSE)
self.assertRaises(exception.IloError,
self.client._change_iscsi_settings,
properties)
properties, [])
check_bios_mock.assert_called_once_with()
mappings_mock.assert_called_once_with(bios_settings)
check_iscsi_mock.assert_called_once_with()

View File

@ -1,37 +1,65 @@
{
"@odata.type": "#EthernetInterface.v1_0_2.EthernetInterface",
"Id": "1",
"Name": "Ethernet Interface",
"Description": "System NIC 1",
"Status": {
"State": "Enabled",
"Health": "OK"
"default": {
"@odata.type": "#EthernetInterface.v1_0_2.EthernetInterface",
"Id": "1",
"Name": "Ethernet Interface",
"Description": "System NIC 1",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"PermanentMACAddress": "12:44:6A:3B:04:11",
"MACAddress": "12:44:6A:3B:04:11",
"SpeedMbps": 1000,
"FullDuplex": true,
"HostName": "web483",
"FQDN": "web483.contoso.com",
"IPv6DefaultGateway": "fe80::3ed9:2bff:fe34:600",
"NameServers": [
"names.contoso.com"
],
"IPv4Addresses": [{
"Address": "192.168.0.10",
"SubnetMask": "255.255.252.0",
"AddressOrigin": "Static",
"Gateway": "192.168.0.1"
}],
"IPv6Addresses": [{
"Address": "fe80::1ec1:deff:fe6f:1e24",
"PrefixLength": 64,
"AddressOrigin": "Static",
"AddressState": "Preferred"
}],
"VLANs": {
"@odata.id": "/redfish/v1/Systems/437XR1138R2/EthernetInterfaces/12446A3B0411/VLANs"
},
"@odata.context": "/redfish/v1/$metadata#EthernetInterface.EthernetInterface",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/EthernetInterfaces/12446A3B0411"
},
"PermanentMACAddress": "12:44:6A:3B:04:11",
"MACAddress": "12:44:6A:3B:04:11",
"SpeedMbps": 1000,
"FullDuplex": true,
"HostName": "web483",
"FQDN": "web483.contoso.com",
"IPv6DefaultGateway": "fe80::3ed9:2bff:fe34:600",
"NameServers": [
"names.contoso.com"
],
"IPv4Addresses": [{
"Address": "192.168.0.10",
"SubnetMask": "255.255.252.0",
"AddressOrigin": "Static",
"Gateway": "192.168.0.1"
}],
"IPv6Addresses": [{
"Address": "fe80::1ec1:deff:fe6f:1e24",
"PrefixLength": 64,
"AddressOrigin": "Static",
"AddressState": "Preferred"
}],
"VLANs": {
"@odata.id": "/redfish/v1/Systems/437XR1138R2/EthernetInterfaces/12446A3B0411/VLANs"
},
"@odata.context": "/redfish/v1/$metadata#EthernetInterface.EthernetInterface",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/EthernetInterfaces/12446A3B0411"
"latest": {
"@odata.context": "/redfish/v1/$metadata#EthernetInterface.EthernetInterface",
"@odata.etag": "W/\"72E9391E\"",
"@odata.id": "/redfish/v1/Systems/1/EthernetInterfaces/6/",
"@odata.type": "#EthernetInterface.v1_4_1.EthernetInterface",
"Id": "6",
"FullDuplex": true,
"IPv4Addresses": [],
"IPv4StaticAddresses": [],
"IPv6AddressPolicyTable": [],
"IPv6Addresses": [],
"IPv6StaticAddresses": [],
"IPv6StaticDefaultGateways": [],
"LinkStatus": null,
"MACAddress": "98:f2:b3:2a:0e:3d",
"Name": "",
"NameServers": [],
"SpeedMbps": null,
"StaticNameServers": [],
"Status": {
"Health": null,
"State": null
},
"UefiDevicePath": "PciRoot(0x0)/Pci(0x1C,0x0)/Pci(0x0,0x0)"
}
}

View File

@ -30,7 +30,8 @@ class EthernetInterfaceTestCase(testtools.TestCase):
eth_file = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface.json')
with open(eth_file, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.conn.get.return_value.json.return_value = json.loads(
f.read())['default']
eth_path = ("/redfish/v1/Systems/437XR1138R2/EthernetInterfaces/"
"12446A3B0411")
@ -102,7 +103,30 @@ class EthernetInterfaceCollectionTestCase(testtools.TestCase):
path = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface.json')
with open(path, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.conn.get.return_value.json.return_value = json.loads(
f.read())['default']
expected_summary = {'Port 1': '12:44:6A:3B:04:11'}
actual_summary = self.sys_eth_col.summary
self.assertEqual(expected_summary, actual_summary)
def test_get_uefi_device_path_by_mac(self):
self.conn.get.return_value.json.reset_mock()
path = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface.json')
with open(path, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(
f.read())['latest']
result = self.sys_eth_col.get_uefi_device_path_by_mac(
'98:f2:b3:2a:0e:3d')
self.assertEqual(
'PciRoot(0x0)/Pci(0x1C,0x0)/Pci(0x0,0x0)', result)
def test_get_all_macs(self):
self.conn.get.return_value.json.reset_mock()
path = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface.json')
with open(path, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(
f.read())['latest']
result = self.sys_eth_col.get_all_macs()
self.assertEqual(['98:f2:b3:2a:0e:3d'], result)

View File

@ -309,7 +309,7 @@ class HPESystemTestCase(testtools.TestCase):
eth_coll = json.loads(f.read())
with open('proliantutils/tests/redfish/json_samples/'
'ethernet_interface.json', 'r') as f:
eth_value = (json.loads(f.read()))
eth_value = (json.loads(f.read())['default'])
self.conn.get.return_value.json.side_effect = [eth_coll,
eth_value]
actual_macs = self.sys_inst.ethernet_interfaces.summary
@ -339,7 +339,7 @@ class HPESystemTestCase(testtools.TestCase):
eth_coll = json.loads(f.read())
with open('proliantutils/tests/redfish/json_samples/'
'ethernet_interface.json', 'r') as f:
eth_value = (json.loads(f.read()))
eth_value = (json.loads(f.read())['default'])
self.conn.get.return_value.json.side_effect = [eth_coll,
eth_value]
actual_macs = self.sys_inst.ethernet_interfaces.summary
@ -1127,3 +1127,53 @@ class HPESystemTestCase(testtools.TestCase):
self.assertEqual(list(set(types)), self.sys_inst.get_disk_types())
array_controller_by_model_mock.assert_called_once_with(
'HPE Smart Array P408i-p SR Gen10')
@mock.patch.object(ethernet_interface.EthernetInterfaceCollection,
'get_uefi_device_path_by_mac')
def test_get_nic_association_name_by_mac(self, uefi_device_path_mock):
with open('proliantutils/tests/redfish/'
'json_samples/bios.json', 'r') as f:
bios_json = json.loads(f.read())
with open('proliantutils/tests/redfish/'
'json_samples/bios_mappings.json', 'r') as f:
bios_mappings_json = json.loads(f.read())
path = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface_collection.json')
with open(path, 'r') as f:
eth_coll = json.loads(f.read())
self.conn.get.return_value.json.side_effect = [
bios_json['Default'], bios_mappings_json['Default'],
eth_coll]
(uefi_device_path_mock.
return_value) = 'PciRoot(0x2)/Pci(0x0,0x0)/Pci(0x0,0x2)'
result = self.sys_inst.get_nic_association_name_by_mac(
'12:44:6A:3B:04:11')
self.assertEqual(result, 'NicBoot1')
@mock.patch.object(ethernet_interface.EthernetInterfaceCollection,
'get_all_macs')
def test_validate_macs(self, get_all_macs_mock):
path = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface_collection.json')
with open(path, 'r') as f:
eth_coll = json.loads(f.read())
self.conn.get.return_value.json.side_effect = [eth_coll]
get_all_macs_mock.return_value = [
'12:44:6a:3b:04:11', '13:44:6a:3b:04:13']
result = self.sys_inst.validate_macs(['12:44:6a:3b:04:11'])
self.assertEqual(result, None)
@mock.patch.object(ethernet_interface.EthernetInterfaceCollection,
'get_all_macs')
def test_validate_macs_failed(self, get_all_macs_mock):
path = ('proliantutils/tests/redfish/json_samples/'
'ethernet_interface_collection.json')
with open(path, 'r') as f:
eth_coll = json.loads(f.read())
self.conn.get.return_value.json.side_effect = eth_coll
get_all_macs_mock.return_value = [
'12:44:6a:3b:04:11', '13:44:6a:3b:04:13']
self.assertRaisesRegex(
exception.InvalidInputError,
"Given macs: \['12:44:6A:3B:04:15'\] not found in the system",
self.sys_inst.validate_macs, ['12:44:6A:3B:04:15'])

View File

@ -1,4 +1,4 @@
# Copyright 2017 Hewlett Packard Enterprise Development LP
# Copyright 2019 Hewlett Packard Enterprise Development LP
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -1093,7 +1093,27 @@ class RedfishOperationsTestCase(testtools.TestCase):
'iqn.2011-07.com.example.server:test1',
'1', '10.10.1.30')
change_iscsi_target_settings_mock.assert_called_once_with(
self.rf_client, iscsi_variables)
self.rf_client, iscsi_variables, [])
@mock.patch.object(redfish.RedfishOperations,
'_change_iscsi_target_settings', autospec=True)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_set_iscsi_info_uefi_with_mac(self, _uefi_boot_mode_mock,
change_iscsi_target_settings_mock):
_uefi_boot_mode_mock.return_value = True
iscsi_variables = {
'iSCSITargetName': 'iqn.2011-07.com.example.server:test1',
'iSCSITargetInfoViaDHCP': False,
'iSCSILUN': '1',
'iSCSIConnection': 'Enabled',
'iSCSITargetIpAddress': '10.10.1.30',
'iSCSITargetTcpPort': 3260}
self.rf_client.set_iscsi_info(
'iqn.2011-07.com.example.server:test1',
'1', '10.10.1.30', macs=['98:f2:b3:ee:f4:00'])
change_iscsi_target_settings_mock.assert_called_once_with(
self.rf_client, iscsi_variables, ['98:f2:b3:ee:f4:00'])
@mock.patch.object(redfish.RedfishOperations,
'_change_iscsi_target_settings', autospec=True)
@ -1116,7 +1136,7 @@ class RedfishOperationsTestCase(testtools.TestCase):
'iqn.2011-07.com.example.server:test1',
'1', '10.10.1.30', 3260, 'CHAP', 'admin', 'password')
change_iscsi_target_settings_mock.assert_called_once_with(
self.rf_client, iscsi_variables)
self.rf_client, iscsi_variables, [])
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
@ -1138,7 +1158,20 @@ class RedfishOperationsTestCase(testtools.TestCase):
'iSCSIConnection': 'Disabled'}
self.rf_client.unset_iscsi_info()
change_iscsi_target_settings_mock.assert_called_once_with(
self.rf_client, iscsi_variables)
self.rf_client, iscsi_variables, [])
@mock.patch.object(redfish.RedfishOperations,
'_change_iscsi_target_settings', autospec=True)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_unset_iscsi_info_uefi_with_mac(self, _uefi_boot_mode_mock,
change_iscsi_target_settings_mock):
_uefi_boot_mode_mock.return_value = True
iscsi_variables = {
'iSCSIConnection': 'Disabled'}
self.rf_client.unset_iscsi_info(['98:f2:b3:ee:f4:00'])
change_iscsi_target_settings_mock.assert_called_once_with(
self.rf_client, iscsi_variables, ['98:f2:b3:ee:f4:00'])
@mock.patch.object(iscsi.ISCSISettings, 'update_iscsi_settings')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
@ -1200,10 +1233,66 @@ class RedfishOperationsTestCase(testtools.TestCase):
data = {
'iSCSISources': [iscsi_data1, iscsi_data2]
}
self.rf_client._change_iscsi_target_settings(iscsi_variable)
self.rf_client._change_iscsi_target_settings(iscsi_variable, [])
update_iscsi_settings_mock.assert_called_once_with(
data)
@mock.patch.object(pro_sys.HPESystem, 'validate_macs')
@mock.patch.object(pro_sys.HPESystem, 'get_nic_association_name_by_mac')
@mock.patch.object(iscsi.ISCSISettings, 'update_iscsi_settings')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test__change_iscsi_target_settings_with_mac(
self, get_system_mock, update_iscsi_settings_mock,
get_nic_association_mock, validate_macs_mock):
with open('proliantutils/tests/redfish/'
'json_samples/system.json', 'r') as f:
system_json = json.loads(f.read())
with open('proliantutils/tests/redfish/'
'json_samples/bios.json', 'r') as f:
bios_json = json.loads(f.read())
with open('proliantutils/tests/redfish/'
'json_samples/iscsi.json', 'r') as f:
iscsi_json = json.loads(f.read())
with open('proliantutils/tests/redfish/'
'json_samples/iscsi_settings.json', 'r') as f:
iscsi_settings_json = json.loads(f.read())
self.conn = mock.Mock()
self.conn.get.return_value.json.side_effect = [
system_json['default'], bios_json['Default'],
iscsi_json,
iscsi_settings_json['Default']]
self.sys_inst = pro_sys.HPESystem(self.conn,
'/redfish/v1/Systems/437XR1138R2',
redfish_version='1.0.2')
get_system_mock.return_value = self.sys_inst
get_nic_association_mock.return_value = 'NicBoot1'
iscsi_variable = {'iSCSITargetName':
'iqn.2011-07.com.example.server:test1',
'iSCSILUN': '1',
'iSCSITargetIpAddress': '10.10.1.30',
'iSCSITargetTcpPort': 3260,
'iSCSITargetInfoViaDHCP': False,
'iSCSIConnection': 'Enabled'}
iscsi_data = {'iSCSITargetName':
'iqn.2011-07.com.example.server:test1',
'iSCSILUN': '1',
'iSCSITargetIpAddress': '10.10.1.30',
'iSCSITargetTcpPort': 3260,
'iSCSITargetInfoViaDHCP': False,
'iSCSIConnection': 'Enabled',
'iSCSIAttemptName': 'NicBoot1',
'iSCSINicSource': 'NicBoot1',
'iSCSIAttemptInstance': 1}
data = {
'iSCSISources': [iscsi_data]
}
self.rf_client._change_iscsi_target_settings(
iscsi_variable, ['98:f2:b3:ee:f4:00'])
update_iscsi_settings_mock.assert_called_once_with(
data)
validate_macs_mock.assert_called_once_with(['98:f2:b3:ee:f4:00'])
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test__change_iscsi_target_settings_failed_getting_mappings(
self, get_system_mock):
@ -1215,11 +1304,10 @@ class RedfishOperationsTestCase(testtools.TestCase):
exception.IloError,
"The Redfish controller failed to get the "
"bios mappings. Error",
self.rf_client._change_iscsi_target_settings,
'{}')
self.rf_client._change_iscsi_target_settings, {}, [])
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test__change_iscsi_target_settings_no_nics(
def test__change_iscsi_target_settings_no_macs(
self, get_system_mock):
with open('proliantutils/tests/redfish/'
'json_samples/system.json', 'r') as f:
@ -1240,9 +1328,21 @@ class RedfishOperationsTestCase(testtools.TestCase):
get_system_mock.return_value = self.sys_inst
self.assertRaisesRegex(
exception.IloError,
"No nics were found on the system",
self.rf_client._change_iscsi_target_settings,
'{}')
"No macs were found on the system",
self.rf_client._change_iscsi_target_settings, {}, [])
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test__change_iscsi_target_settings_mac_invalid(
self, get_system_mock):
msg = ("Given macs: %(macs)s not found in the system"
% {'macs': str(['12:44:6A:3B:04:15'])})
get_system_mock.return_value.validate_macs.side_effect = (
exception.InvalidInputError(msg))
self.assertRaisesRegex(
exception.InvalidInputError,
"Given macs: \['12:44:6A:3B:04:15'\] not found in the system",
self.rf_client._change_iscsi_target_settings, {},
['12:44:6A:3B:04:15'])
@mock.patch.object(iscsi.ISCSISettings, 'update_iscsi_settings')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
@ -1287,8 +1387,7 @@ class RedfishOperationsTestCase(testtools.TestCase):
exception.IloError,
'The Redfish controller is failed to update iSCSI '
'settings.',
self.rf_client._change_iscsi_target_settings,
iscsi_variable)
self.rf_client._change_iscsi_target_settings, iscsi_variable, [])
@mock.patch.object(iscsi.ISCSISettings, 'update_iscsi_settings')
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',