Fix the logic for fetching the gpu device count
This patch fixes the logic for fetching the gpu device count on Gen9 and above. The Active gpu devices are not listed by RIBCL while it can be achieved via RIS. Change-Id: Iabac9ab2473848683f0ae7661aac064370c26d9b
This commit is contained in:
@@ -26,11 +26,13 @@ SUPPORTED_RIS_METHODS = [
|
||||
'get_current_boot_mode',
|
||||
'get_host_power_status',
|
||||
'get_http_boot_url',
|
||||
'get_ilo_firmware_version_as_major_minor',
|
||||
'get_one_time_boot',
|
||||
'get_pending_boot_mode',
|
||||
'get_persistent_boot_device',
|
||||
'get_product_name',
|
||||
'get_secure_boot_mode',
|
||||
'get_server_capabilities',
|
||||
'get_vm_status',
|
||||
'hold_pwr_btn',
|
||||
'insert_virtual_media',
|
||||
@@ -355,16 +357,9 @@ class IloClient(operations.IloOperations):
|
||||
:raises: IloCommandNotSupportedError, if the command is not supported
|
||||
on the server.
|
||||
"""
|
||||
capabilities = {}
|
||||
if 'Gen9' in self.model:
|
||||
capabilities = self.ris.get_server_capabilities()
|
||||
data = self.ribcl.get_host_health_data()
|
||||
gpu = self.ribcl._get_number_of_gpu_devices_connected(data)
|
||||
capabilities.update(gpu)
|
||||
major_minor = self.ris.get_ilo_firmware_version_as_major_minor()
|
||||
else:
|
||||
capabilities = self.ribcl.get_server_capabilities()
|
||||
major_minor = self.ribcl.get_ilo_firmware_version_as_major_minor()
|
||||
capabilities = self._call_method('get_server_capabilities')
|
||||
major_minor = (
|
||||
self._call_method('get_ilo_firmware_version_as_major_minor'))
|
||||
|
||||
# NOTE(vmud213): Even if it is None, pass it on to get_nic_capacity
|
||||
# as we still want to try getting nic capacity through ipmitool
|
||||
|
||||
@@ -48,6 +48,19 @@ POWER_STATE = {
|
||||
'OFF': 'ForceOff',
|
||||
}
|
||||
|
||||
# The PCI standards mention following categories of PCI devices as
|
||||
# GPU devices.
|
||||
# Base Class Code 03 indicate VGA devices
|
||||
# Sub Class Code
|
||||
# 00h: VGA-compatible controller
|
||||
# 01h: XGA controller
|
||||
# 02h: 3D controller
|
||||
# 80h: Other display controller
|
||||
# RIS data reports the SubclassCode in integer rather than in hexadecimal form.
|
||||
|
||||
CLASSCODE_FOR_GPU_DEVICES = [3]
|
||||
SUBCLASSCODE_FOR_GPU_DEVICES = [0, 1, 2, 128]
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
@@ -376,6 +389,45 @@ class RISOperations(operations.IloOperations):
|
||||
' does not exist')
|
||||
raise exception.IloCommandNotSupportedError(msg)
|
||||
|
||||
def _get_pci_devices(self):
|
||||
"""Gets the PCI devices.
|
||||
|
||||
:returns: PCI devices list if the pci resource exist.
|
||||
:raises: IloCommandNotSupportedError if the PCI resource
|
||||
doesn't exist.
|
||||
:raises: IloError, on an error from iLO.
|
||||
"""
|
||||
|
||||
system = self._get_host_details()
|
||||
if ('links' in system['Oem']['Hp'] and
|
||||
'PCIDevices' in system['Oem']['Hp']['links']):
|
||||
# Get the PCI URI and Settings
|
||||
pci_uri = system['Oem']['Hp']['links']['PCIDevices']['href']
|
||||
status, headers, pci_device_list = self._rest_get(pci_uri)
|
||||
|
||||
if status >= 300:
|
||||
msg = self._get_extended_error(pci_device_list)
|
||||
raise exception.IloError(msg)
|
||||
|
||||
return pci_device_list
|
||||
|
||||
else:
|
||||
msg = ('links/PCIDevices section in ComputerSystem/Oem/Hp'
|
||||
' does not exist')
|
||||
raise exception.IloCommandNotSupportedError(msg)
|
||||
|
||||
def _get_gpu_pci_devices(self):
|
||||
"""Returns the list of gpu devices."""
|
||||
pci_device_list = self._get_pci_devices()
|
||||
|
||||
gpu_list = []
|
||||
items = pci_device_list['Items']
|
||||
for item in items:
|
||||
if item['ClassCode'] in CLASSCODE_FOR_GPU_DEVICES:
|
||||
if item['SubclassCode'] in SUBCLASSCODE_FOR_GPU_DEVICES:
|
||||
gpu_list.append(item)
|
||||
return gpu_list
|
||||
|
||||
def _get_bios_settings_resource(self, data):
|
||||
"""Get the BIOS settings resource."""
|
||||
try:
|
||||
@@ -1064,6 +1116,7 @@ class RISOperations(operations.IloOperations):
|
||||
system['Oem']['Hp']['Bios']['Current']['VersionString'])
|
||||
capabilities['rom_firmware_version'] = rom_firmware_version
|
||||
capabilities.update(self._get_ilo_firmware_version())
|
||||
capabilities.update(self._get_number_of_gpu_devices_connected())
|
||||
try:
|
||||
self.get_secure_boot_mode()
|
||||
capabilities['secure_boot'] = 'true'
|
||||
@@ -1546,3 +1599,9 @@ class RISOperations(operations.IloOperations):
|
||||
LOG.debug(self._('Flashing firmware file ... in progress %d%%'),
|
||||
fw_update_progress_percent)
|
||||
return fw_update_state, fw_update_progress_percent
|
||||
|
||||
def _get_number_of_gpu_devices_connected(self):
|
||||
"""get the number of GPU devices connected."""
|
||||
gpu_devices = self._get_gpu_pci_devices()
|
||||
gpu_devices_count = len(gpu_devices)
|
||||
return {'pci_gpu_devices': gpu_devices_count}
|
||||
|
||||
@@ -3727,3 +3727,151 @@ UEFI_BOOTSOURCES_MISSING = """
|
||||
}
|
||||
}
|
||||
"""
|
||||
PCI_DEVICE_DETAILS_NO_GPU = """
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Systems/Members/1/PCIDevices",
|
||||
"@odata.id": "/redfish/v1/Systems/1/PCIDevices/",
|
||||
"@odata.type": "#HpServerPciDeviceCollection.HpServerPciDeviceCollection",
|
||||
"Description": " PciDevices view",
|
||||
"Items": [
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Systems/Members/\
|
||||
1/PCIDevices/Members/$entity",
|
||||
"@odata.id": "/redfish/v1/Systems/1/PCIDevices/6/",
|
||||
"@odata.type": "#HpServerPciDevice.1.0.0.HpServerPciDevice",
|
||||
"BusNumber": 132,
|
||||
"ClassCode": 6,
|
||||
"DeviceID": 34631,
|
||||
"DeviceInstance": 2,
|
||||
"DeviceLocation": "PCI Slot",
|
||||
"DeviceNumber": 0,
|
||||
"DeviceSubInstance": 1,
|
||||
"DeviceType": "Other PCI Device",
|
||||
"FunctionNumber": 0,
|
||||
"Id": "6",
|
||||
"Name": "PCIe Controller",
|
||||
"SegmentNumber": 0,
|
||||
"StructuredName": "PCI.Slot.2.1",
|
||||
"SubclassCode": 4,
|
||||
"SubsystemDeviceID": 34631,
|
||||
"SubsystemVendorID": 4277,
|
||||
"Type": "HpServerPciDevice.1.0.0",
|
||||
"UEFIDevicePath": "PciRoot(0x1)/Pci(0x3,0x0)/Pci(0x0,0x0)",
|
||||
"VendorID": 4277,
|
||||
"links": {
|
||||
"self": {
|
||||
"href": "/rest/v1/Systems/1/PCIDevices/6"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
PCI_GPU_LIST = """
|
||||
[
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Systems/Members/1\
|
||||
/PCIDevices/Members/$entity",
|
||||
"@odata.id": "/redfish/v1/Systems/1/PCIDevices/6/",
|
||||
"@odata.type": "#HpServerPciDevice.1.0.0.HpServerPciDevice",
|
||||
"BusNumber": 5,
|
||||
"ClassCode": 3,
|
||||
"DeviceID": 26528,
|
||||
"DeviceInstance": 3,
|
||||
"DeviceLocation": "PCI Slot",
|
||||
"DeviceNumber": 0,
|
||||
"DeviceSubInstance": 1,
|
||||
"DeviceType": "Other PCI Device",
|
||||
"FunctionNumber": 0,
|
||||
"Id": "6",
|
||||
"Name": "HAWAII XTGL",
|
||||
"SegmentNumber": 0,
|
||||
"StructuredName": "PCI.Slot.3.1",
|
||||
"SubclassCode": 128,
|
||||
"SubsystemDeviceID": 821,
|
||||
"SubsystemVendorID": 4098,
|
||||
"Type": "HpServerPciDevice.1.0.0",
|
||||
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/\
|
||||
Pci(0x8,0x0)/Pci(0x0,0x0)",
|
||||
"VendorID": 4098,
|
||||
"links": {
|
||||
"self": {
|
||||
"href": "/rest/v1/Systems/1/PCIDevices/6"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
PCI_DEVICE_DETAILS = """
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Systems/Members/1/PCIDevices",
|
||||
"@odata.id": "/redfish/v1/Systems/1/PCIDevices/",
|
||||
"@odata.type": "#HpServerPciDeviceCollection.HpServerPciDeviceCollection",
|
||||
"Description": " PciDevices view",
|
||||
"Items": [
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Systems/Members/\
|
||||
1/PCIDevices/Members/$entity",
|
||||
"@odata.id": "/redfish/v1/Systems/1/PCIDevices/6/",
|
||||
"@odata.type": "#HpServerPciDevice.1.0.0.HpServerPciDevice",
|
||||
"BusNumber": 132,
|
||||
"ClassCode": 6,
|
||||
"DeviceID": 34631,
|
||||
"DeviceInstance": 2,
|
||||
"DeviceLocation": "PCI Slot",
|
||||
"DeviceNumber": 0,
|
||||
"DeviceSubInstance": 1,
|
||||
"DeviceType": "Other PCI Device",
|
||||
"FunctionNumber": 0,
|
||||
"Id": "6",
|
||||
"Name": "PCIe Controller",
|
||||
"SegmentNumber": 0,
|
||||
"StructuredName": "PCI.Slot.2.1",
|
||||
"SubclassCode": 4,
|
||||
"SubsystemDeviceID": 34631,
|
||||
"SubsystemVendorID": 4277,
|
||||
"Type": "HpServerPciDevice.1.0.0",
|
||||
"UEFIDevicePath": "PciRoot(0x1)/Pci(0x3,0x0)/Pci(0x0,0x0)",
|
||||
"VendorID": 4277,
|
||||
"links": {
|
||||
"self": {
|
||||
"href": "/rest/v1/Systems/1/PCIDevices/6"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Systems/Members/1\
|
||||
/PCIDevices/Members/$entity",
|
||||
"@odata.id": "/redfish/v1/Systems/1/PCIDevices/6/",
|
||||
"@odata.type": "#HpServerPciDevice.1.0.0.HpServerPciDevice",
|
||||
"BusNumber": 5,
|
||||
"ClassCode": 3,
|
||||
"DeviceID": 26528,
|
||||
"DeviceInstance": 3,
|
||||
"DeviceLocation": "PCI Slot",
|
||||
"DeviceNumber": 0,
|
||||
"DeviceSubInstance": 1,
|
||||
"DeviceType": "Other PCI Device",
|
||||
"FunctionNumber": 0,
|
||||
"Id": "6",
|
||||
"Name": "HAWAII XTGL",
|
||||
"SegmentNumber": 0,
|
||||
"StructuredName": "PCI.Slot.3.1",
|
||||
"SubclassCode": 128,
|
||||
"SubsystemDeviceID": 821,
|
||||
"SubsystemVendorID": 4098,
|
||||
"Type": "HpServerPciDevice.1.0.0",
|
||||
"UEFIDevicePath": "PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/\
|
||||
Pci(0x8,0x0)/Pci(0x0,0x0)",
|
||||
"VendorID": 4098,
|
||||
"links": {
|
||||
"self": {
|
||||
"href": "/rest/v1/Systems/1/PCIDevices/6"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# under the License.
|
||||
"""Test class for Client Module."""
|
||||
|
||||
import json
|
||||
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
@@ -23,7 +21,6 @@ from proliantutils.ilo import client
|
||||
from proliantutils.ilo import ipmi
|
||||
from proliantutils.ilo import ribcl
|
||||
from proliantutils.ilo import ris
|
||||
from proliantutils.tests.ilo import ribcl_sample_outputs as constants
|
||||
|
||||
|
||||
class IloClientInitTestCase(testtools.TestCase):
|
||||
@@ -330,24 +327,17 @@ class IloClientTestCase(testtools.TestCase):
|
||||
|
||||
@mock.patch.object(ris.RISOperations,
|
||||
'get_ilo_firmware_version_as_major_minor')
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_host_health_data')
|
||||
@mock.patch.object(ribcl.RIBCLOperations,
|
||||
'_get_number_of_gpu_devices_connected')
|
||||
@mock.patch.object(ipmi, 'get_nic_capacity')
|
||||
@mock.patch.object(ris.RISOperations, 'get_server_capabilities')
|
||||
def test_get_server_capabilities_no_nic_Gen9(self, cap_mock, nic_mock,
|
||||
gpu_mock, host_mock, mm_mock):
|
||||
info = {'address': "1.2.3.4", 'username': "admin", 'password': "Admin"}
|
||||
data = constants.GET_EMBEDDED_HEALTH_OUTPUT
|
||||
json_data = json.loads(data)
|
||||
host_mock.return_value = json_data
|
||||
mm_mock):
|
||||
str_val = mm_mock.return_value = '2.10'
|
||||
self.client.model = 'Gen9'
|
||||
nic_mock.return_value = None
|
||||
gpu_mock.return_value = {'pci_gpu_devices': 2}
|
||||
cap_mock.return_value = {'ilo_firmware_version': '2.10',
|
||||
'rom_firmware_version': 'x',
|
||||
'server_model': 'Gen9',
|
||||
'pci_gpu_devices': 2,
|
||||
'secure_boot': 'true'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
cap_mock.assert_called_once_with()
|
||||
@@ -358,28 +348,20 @@ class IloClientTestCase(testtools.TestCase):
|
||||
'pci_gpu_devices': 2,
|
||||
'secure_boot': 'true'}
|
||||
self.assertEqual(expected_capabilities, capabilities)
|
||||
self.assertEqual(info, self.client.info)
|
||||
|
||||
@mock.patch.object(ris.RISOperations,
|
||||
'get_ilo_firmware_version_as_major_minor')
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_host_health_data')
|
||||
@mock.patch.object(ribcl.RIBCLOperations,
|
||||
'_get_number_of_gpu_devices_connected')
|
||||
@mock.patch.object(ipmi, 'get_nic_capacity')
|
||||
@mock.patch.object(ris.RISOperations, 'get_server_capabilities')
|
||||
def test_get_server_capabilities_Gen9(self, cap_mock, nic_mock,
|
||||
gpu_mock, host_mock, mm_mock):
|
||||
info = {'address': "1.2.3.4", 'username': "admin", 'password': "Admin"}
|
||||
data = constants.GET_EMBEDDED_HEALTH_OUTPUT
|
||||
json_data = json.loads(data)
|
||||
host_mock.return_value = json_data
|
||||
mm_mock):
|
||||
str_val = mm_mock.return_value = '2.10'
|
||||
self.client.model = 'Gen9'
|
||||
gpu_mock.return_value = {'pci_gpu_devices': 2}
|
||||
nic_mock.return_value = '10Gb'
|
||||
cap_mock.return_value = {'ilo_firmware_version': '2.10',
|
||||
'rom_firmware_version': 'x',
|
||||
'server_model': 'Gen9',
|
||||
'pci_gpu_devices': 2,
|
||||
'secure_boot': 'true'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
cap_mock.assert_called_once_with()
|
||||
@@ -391,7 +373,6 @@ class IloClientTestCase(testtools.TestCase):
|
||||
'secure_boot': 'true',
|
||||
'nic_capacity': '10Gb'}
|
||||
self.assertEqual(expected_capabilities, capabilities)
|
||||
self.assertEqual(info, self.client.info)
|
||||
|
||||
@mock.patch.object(client.IloClient, '_call_method')
|
||||
def test_activate_license(self, call_mock):
|
||||
|
||||
@@ -386,19 +386,23 @@ class IloRisTestCase(testtools.TestCase):
|
||||
validate_mock.assert_called_once_with(ris_outputs.GET_HEADERS,
|
||||
settings_uri)
|
||||
|
||||
@mock.patch.object(ris.RISOperations,
|
||||
'_get_number_of_gpu_devices_connected')
|
||||
@mock.patch.object(ris.RISOperations, 'get_secure_boot_mode')
|
||||
@mock.patch.object(ris.RISOperations, '_get_ilo_firmware_version')
|
||||
@mock.patch.object(ris.RISOperations, '_get_host_details')
|
||||
def test_get_server_capabilities(self, get_details_mock, ilo_firm_mock,
|
||||
secure_mock):
|
||||
secure_mock, gpu_mock):
|
||||
host_details = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP)
|
||||
get_details_mock.return_value = host_details
|
||||
ilo_firm_mock.return_value = {'ilo_firmware_version': 'iLO 4 v2.20'}
|
||||
gpu_mock.return_value = {'pci_gpu_devices': 2}
|
||||
secure_mock.return_value = False
|
||||
expected_caps = {'secure_boot': 'true',
|
||||
'ilo_firmware_version': 'iLO 4 v2.20',
|
||||
'rom_firmware_version': u'I36 v1.40 (01/28/2015)',
|
||||
'server_model': u'ProLiant BL460c Gen9'}
|
||||
'server_model': u'ProLiant BL460c Gen9',
|
||||
'pci_gpu_devices': 2}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
self.assertEqual(expected_caps, capabilities)
|
||||
|
||||
@@ -1680,6 +1684,74 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
|
||||
check_bios_mock.assert_called_once_with()
|
||||
boot_mock.assert_called_once_with(bios_settings)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_rest_get')
|
||||
@mock.patch.object(ris.RISOperations, '_get_host_details')
|
||||
def test__get_pci_devices(self, get_host_details_mock, get_mock):
|
||||
system_data = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP)
|
||||
get_host_details_mock.return_value = system_data
|
||||
pci_uri = '/rest/v1/Systems/1/PCIDevices'
|
||||
pci_device_list = json.loads(ris_outputs.PCI_DEVICE_DETAILS)
|
||||
|
||||
get_mock.return_value = (200, ris_outputs.GET_HEADERS,
|
||||
pci_device_list)
|
||||
self.client._get_pci_devices()
|
||||
get_mock.assert_called_once_with(pci_uri)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_rest_get')
|
||||
@mock.patch.object(ris.RISOperations, '_get_host_details')
|
||||
def test__get_pci_devices_fail(self, get_host_details_mock,
|
||||
get_mock):
|
||||
system_data = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP)
|
||||
get_host_details_mock.return_value = system_data
|
||||
pci_uri = '/rest/v1/Systems/1/PCIDevices'
|
||||
pci_device_list = json.loads(ris_outputs.PCI_DEVICE_DETAILS)
|
||||
get_mock.return_value = (301, ris_outputs.GET_HEADERS,
|
||||
pci_device_list)
|
||||
self.assertRaises(exception.IloError,
|
||||
self.client._get_pci_devices)
|
||||
get_mock.assert_called_once_with(pci_uri)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_get_host_details')
|
||||
def test__get_pci_devices_not_supported(self, get_details_mock):
|
||||
host_response = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP)
|
||||
del host_response['Oem']['Hp']['links']['PCIDevices']
|
||||
get_details_mock.return_value = host_response
|
||||
self.assertRaises(exception.IloCommandNotSupportedError,
|
||||
self.client._get_pci_devices)
|
||||
get_details_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_get_pci_devices')
|
||||
def test__get_gpu_pci_devices(self, pci_mock):
|
||||
pci_mock.return_value = json.loads(ris_outputs.PCI_DEVICE_DETAILS)
|
||||
pci_gpu_list = self.client._get_gpu_pci_devices()
|
||||
self.assertEqual(pci_gpu_list, json.loads(ris_outputs.PCI_GPU_LIST))
|
||||
self.assertTrue(pci_mock.called)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_get_pci_devices')
|
||||
def test__get_gpu_pci_devices_returns_empty(self, pci_mock):
|
||||
pci_response = json.loads(ris_outputs.PCI_DEVICE_DETAILS_NO_GPU)
|
||||
pci_mock.return_value = pci_response
|
||||
pci_gpu_list = self.client._get_gpu_pci_devices()
|
||||
self.assertEqual(len(pci_gpu_list), 0)
|
||||
self.assertTrue(pci_mock.called)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_get_pci_devices')
|
||||
def test__get_gpu_pci_devices_fail_not_supported_error(self, pci_mock):
|
||||
msg = ('links/PCIDevices section in ComputerSystem/Oem/Hp'
|
||||
' does not exist')
|
||||
pci_mock.side_effect = exception.IloCommandNotSupportedError(msg)
|
||||
self.assertRaises(exception.IloCommandNotSupportedError,
|
||||
self.client._get_gpu_pci_devices)
|
||||
self.assertTrue(pci_mock.called)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_get_gpu_pci_devices')
|
||||
def test__get_number_of_gpu_devices_connected(self, gpu_list_mock):
|
||||
gpu_list_mock.return_value = json.loads(ris_outputs.PCI_GPU_LIST)
|
||||
expected_gpu_count = {'pci_gpu_devices': 1}
|
||||
gpu_count_returned = self.client._get_number_of_gpu_devices_connected()
|
||||
self.assertEqual(gpu_count_returned, expected_gpu_count)
|
||||
self.assertTrue(gpu_list_mock.called)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_get_ilo_details', autospec=True)
|
||||
def test__get_firmware_update_service_resource_traverses_manager_as(
|
||||
self, _get_ilo_details_mock):
|
||||
|
||||
Reference in New Issue
Block a user