Add new cpu_fpgas capabilities to ironic

This patch add cpu_fpgas capabilities for iRMC driver.

Change-Id: I32e4872b20bcf155db7fc741fe75d3f862ecb864
Closes-Bug: #1744893
This commit is contained in:
Nguyen Hung Phuong
2018-01-23 16:14:38 +07:00
parent 8bee470245
commit f2402bf0bc
4 changed files with 101 additions and 43 deletions

View File

@@ -18,8 +18,8 @@ import itertools
from pyghmi import exceptions as ipmi_exception from pyghmi import exceptions as ipmi_exception
from pyghmi.ipmi import command as ipmi_command from pyghmi.ipmi import command as ipmi_command
# F1 1A - Get the number of GPU devices on PCI and the number of CPUs with FPGA # F1 1A - Get the number of specific PCI devices on baremetal
GET_GPU = '0x2E 0xF1 0x80 0x28 0x00 0x1A %s 0x00' GET_PCI = '0x2E 0xF1 0x80 0x28 0x00 0x1A %s 0x00'
# F5 81 - GET TPM STATUS # F5 81 - GET TPM STATUS
GET_TPM_STATUS = '0x2E 0xF5 0x80 0x28 0x00 0x81 0xC0' GET_TPM_STATUS = '0x2E 0xF5 0x80 0x28 0x00 0x81 0xC0'
@@ -118,29 +118,27 @@ def _pci_seq(ipmicmd):
""" """
for i in range(1, 0xff + 1): for i in range(1, 0xff + 1):
try: try:
res = _send_raw_command(ipmicmd, GET_GPU % hex(i)) res = _send_raw_command(ipmicmd, GET_PCI % hex(i))
yield i, res yield i, res
except ipmi_exception.IpmiException as e: except ipmi_exception.IpmiException as e:
raise IPMIFailure( raise IPMIFailure(
"IPMI operation '%(operation)s' failed: %(error)s" % "IPMI operation '%(operation)s' failed: %(error)s" %
{'operation': "GET GPU device quantity", 'error': e}) {'operation': "GET PCI device quantity", 'error': e})
def get_gpu(d_info, pci_device_ids): def get_pci_device(d_info, pci_device_ids):
"""Get quantity of GPU devices on PCI and quantity of CPUs with FPGA. """Get quantity of PCI devices.
Get quantity of GPU devices on PCI and quantity of CPUs with FPGA of the Get quantity of PCI devices of the node.
node.
:param d_info: the list of ipmitool parameters for accessing a node. :param d_info: the list of ipmitool parameters for accessing a node.
:param pci_device_ids: the list contains pairs of <vendorID>/<deviceID> for :param pci_device_ids: the list contains pairs of <vendorID>/<deviceID> for
GPU on PCI. PCI devices.
:returns: a tuple of the number of GPU devices on PCI and the number of :returns: the number of PCI devices.
CPUs with FPGA.
""" """
# note: # note:
# Get quantity of GPU devices on PCI and quantity of CPUs with FPGA: # Get quantity of PCI devices:
# ipmi cmd '0xF1' # ipmi cmd '0xF1'
# #
# $ ipmitool raw 0x2E 0xF1 0x80 0x28 0x00 0x1A 0x01 0x00 # $ ipmitool raw 0x2E 0xF1 0x80 0x28 0x00 0x1A 0x01 0x00
@@ -167,6 +165,6 @@ def get_gpu(d_info, pci_device_ids):
out[7], out[6], out[9], out[8]) out[7], out[6], out[9], out[8])
return accm + 1 if pci_id in pci_device_ids else accm return accm + 1 if pci_id in pci_device_ids else accm
gpu_count = functools.reduce(_pci_count, response, 0) device_count = functools.reduce(_pci_count, response, 0)
return gpu_count return device_count

View File

@@ -492,7 +492,8 @@ def get_essential_properties(report, prop_keys):
def get_capabilities_properties(d_info, def get_capabilities_properties(d_info,
capa_keys, capa_keys,
pci_device_ids, gpu_ids,
fpga_ids=None,
**kwargs): **kwargs):
"""get capabilities properties """get capabilities properties
@@ -502,8 +503,10 @@ def get_capabilities_properties(d_info,
:param d_info: the dictionary of ipmitool parameters for accessing a node. :param d_info: the dictionary of ipmitool parameters for accessing a node.
:param capa_keys: a list of keys for additional capabilities properties. :param capa_keys: a list of keys for additional capabilities properties.
:param pci_device_ids: the list of string contains <vendorID>/<deviceID> :param gpu_ids: the list of string contains <vendorID>/<deviceID>
for GPU. for GPU.
:param fpga_ids: the list of string contains <vendorID>/<deviceID>
for CPU FPGA.
:param kwargs: additional arguments passed to scciclient. :param kwargs: additional arguments passed to scciclient.
:returns: a dictionary which contains keys and their values. :returns: a dictionary which contains keys and their values.
""" """
@@ -529,11 +532,15 @@ def get_capabilities_properties(d_info,
# Sometime the server started but PCI device list building is # Sometime the server started but PCI device list building is
# still in progress so system will response error. We have to wait # still in progress so system will response error. We have to wait
# for some more seconds. # for some more seconds.
if kwargs.get('sleep_flag', False) and 'pci_gpu_devices' in capa_keys: if kwargs.get('sleep_flag', False) and \
any(k in capa_keys for k in ('pci_gpu_devices', 'cpu_fpga')):
time.sleep(5) time.sleep(5)
if 'pci_gpu_devices' in capa_keys: if 'pci_gpu_devices' in capa_keys:
v['pci_gpu_devices'] = ipmi.get_gpu(d_info, pci_device_ids) v['pci_gpu_devices'] = ipmi.get_pci_device(d_info, gpu_ids)
if fpga_ids is not None and 'cpu_fpga' in capa_keys:
v['cpu_fpga'] = ipmi.get_pci_device(d_info, fpga_ids)
if 'trusted_boot' in capa_keys: if 'trusted_boot' in capa_keys:
v['trusted_boot'] = ipmi.get_tpm_status(d_info) v['trusted_boot'] = ipmi.get_tpm_status(d_info)

View File

@@ -78,8 +78,8 @@ class IpmiTestCase(testtools.TestCase):
exec_mock.assert_called_once_with(mock.ANY, cmd) exec_mock.assert_called_once_with(mock.ANY, cmd)
@mock.patch.object(ipmi, '_send_raw_command') @mock.patch.object(ipmi, '_send_raw_command')
def test_get_gpu(self, exec_mock): def test_get_pci(self, exec_mock):
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080'] pci_device_ids = ['0x1000/0x0079', '0x2100/0x0080']
exec_mock.side_effect = ({'command': 0xF1, 'code': 0x00, 'netfn': 0x2F, exec_mock.side_effect = ({'command': 0xF1, 'code': 0x00, 'netfn': 0x2F,
'data': [0x80, 0x28, 0x00, 0x00, 0x00, 0x05, 'data': [0x80, 0x28, 0x00, 0x00, 0x00, 0x05,
@@ -91,22 +91,22 @@ class IpmiTestCase(testtools.TestCase):
cmd1 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x1 0x00" cmd1 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x1 0x00"
cmd2 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x2 0x00" cmd2 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x2 0x00"
actual_out = ipmi.get_gpu(self.info, gpu_ids) actual_out = ipmi.get_pci_device(self.info, pci_device_ids)
self.assertEqual(1, actual_out) self.assertEqual(1, actual_out)
exec_mock.assert_has_calls([mock.call(mock.ANY, cmd1), exec_mock.assert_has_calls([mock.call(mock.ANY, cmd1),
mock.call(mock.ANY, cmd2)]) mock.call(mock.ANY, cmd2)])
@mock.patch.object(ipmi, '_send_raw_command') @mock.patch.object(ipmi, '_send_raw_command')
def test_get_gpu_blank(self, exec_mock): def test_get_pci_blank(self, exec_mock):
gpu_ids = [] pci_device_ids = []
actual_out = ipmi.get_gpu(self.info, gpu_ids) actual_out = ipmi.get_pci_device(self.info, pci_device_ids)
self.assertEqual(0, actual_out) self.assertEqual(0, actual_out)
self.assertTrue(exec_mock.called) self.assertTrue(exec_mock.called)
@mock.patch.object(ipmi, '_send_raw_command') @mock.patch.object(ipmi, '_send_raw_command')
def test_get_gpu_not_found(self, exec_mock): def test_get_pci_not_found(self, exec_mock):
gpu_ids = ['0x1111/0x1179', '0x2100/0x0080'] pci_device_ids = ['0x1111/0x1179', '0x2100/0x0080']
exec_mock.side_effect = ({'command': 0xF1, 'code': 0x00, 'netfn': 0x2F, exec_mock.side_effect = ({'command': 0xF1, 'code': 0x00, 'netfn': 0x2F,
'data': [0x80, 0x28, 0x00, 0x00, 0x00, 0x05, 'data': [0x80, 0x28, 0x00, 0x00, 0x00, 0x05,
@@ -117,23 +117,23 @@ class IpmiTestCase(testtools.TestCase):
'data': [0x80, 0x28, 0x00]}) 'data': [0x80, 0x28, 0x00]})
cmd1 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x1 0x00" cmd1 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x1 0x00"
cmd2 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x2 0x00" cmd2 = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x2 0x00"
actual_out = ipmi.get_gpu(self.info, gpu_ids) actual_out = ipmi.get_pci_device(self.info, pci_device_ids)
self.assertEqual(0, actual_out) self.assertEqual(0, actual_out)
exec_mock.assert_has_calls([mock.call(mock.ANY, cmd1), exec_mock.assert_has_calls([mock.call(mock.ANY, cmd1),
mock.call(mock.ANY, cmd2)]) mock.call(mock.ANY, cmd2)])
@mock.patch.object(ipmi, '_send_raw_command') @mock.patch.object(ipmi, '_send_raw_command')
def test_get_gpu_exception(self, exec_mock): def test_get_pci_exception(self, exec_mock):
gpu_ids = ['0x1111/0x1179', '0x2100/0x0080'] pci_device_ids = ['0x1111/0x1179', '0x2100/0x0080']
exec_mock.side_effect = ipmi_exception.IpmiException('Error') exec_mock.side_effect = ipmi_exception.IpmiException('Error')
cmd = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x1 0x00" cmd = "0x2E 0xF1 0x80 0x28 0x00 0x1A 0x1 0x00"
e = self.assertRaises(ipmi.IPMIFailure, e = self.assertRaises(ipmi.IPMIFailure,
ipmi.get_gpu, ipmi.get_pci_device,
self.info, self.info,
gpu_ids) pci_device_ids)
exec_mock.assert_called_once_with(mock.ANY, cmd) exec_mock.assert_called_once_with(mock.ANY, cmd)
self.assertEqual('IPMI operation \'GET GPU device quantity\' ' self.assertEqual('IPMI operation \'GET PCI device quantity\' '
'failed: Error', str(e)) 'failed: Error', str(e))

View File

@@ -704,7 +704,7 @@ class SCCITestCase(testtools.TestCase):
self.assertEqual(expected, result) self.assertEqual(expected, result)
@mock.patch.object(ipmi, 'get_gpu') @mock.patch.object(ipmi, 'get_pci_device')
@mock.patch.object(snmp, 'get_server_model') @mock.patch.object(snmp, 'get_server_model')
@mock.patch.object(snmp, 'get_irmc_firmware_version') @mock.patch.object(snmp, 'get_irmc_firmware_version')
@mock.patch.object(snmp, 'get_bios_firmware_version') @mock.patch.object(snmp, 'get_bios_firmware_version')
@@ -714,7 +714,7 @@ class SCCITestCase(testtools.TestCase):
bios_mock, bios_mock,
irmc_mock, irmc_mock,
server_mock, server_mock,
gpu_mock): pci_device_mock):
capabilities_properties = {'trusted_boot', 'irmc_firmware_version', capabilities_properties = {'trusted_boot', 'irmc_firmware_version',
'rom_firmware_version', 'server_model', 'rom_firmware_version', 'server_model',
'pci_gpu_devices'} 'pci_gpu_devices'}
@@ -726,7 +726,7 @@ class SCCITestCase(testtools.TestCase):
bios_mock.return_value = 'V4.6.5.4 R1.15.0 for D3099-B1x' bios_mock.return_value = 'V4.6.5.4 R1.15.0 for D3099-B1x'
irmc_mock.return_value = 'iRMC S4-7.82F' irmc_mock.return_value = 'iRMC S4-7.82F'
server_mock.return_value = 'TX2540M1F5' server_mock.return_value = 'TX2540M1F5'
gpu_mock.return_value = 1 pci_device_mock.side_effect = [1]
expected = {'irmc_firmware_version': 'iRMC S4-7.82F', expected = {'irmc_firmware_version': 'iRMC S4-7.82F',
'pci_gpu_devices': 1, 'pci_gpu_devices': 1,
@@ -745,10 +745,57 @@ class SCCITestCase(testtools.TestCase):
bios_mock.assert_called_once_with(mock.ANY) bios_mock.assert_called_once_with(mock.ANY)
irmc_mock.assert_called_once_with(mock.ANY) irmc_mock.assert_called_once_with(mock.ANY)
server_mock.assert_called_once_with(mock.ANY) server_mock.assert_called_once_with(mock.ANY)
gpu_mock.assert_called_once_with(self.irmc_info, pci_device_mock.assert_called_once_with(self.irmc_info, gpu_ids)
gpu_ids)
@mock.patch.object(ipmi, 'get_gpu') @mock.patch.object(ipmi, 'get_pci_device')
@mock.patch.object(snmp, 'get_server_model')
@mock.patch.object(snmp, 'get_irmc_firmware_version')
@mock.patch.object(snmp, 'get_bios_firmware_version')
@mock.patch.object(ipmi, 'get_tpm_status')
def test_get_capabilities_properties_with_cpu_fpga(self,
tpm_mock,
bios_mock,
irmc_mock,
server_mock,
pci_device_mock):
capabilities_properties = {'trusted_boot', 'irmc_firmware_version',
'rom_firmware_version', 'server_model',
'pci_gpu_devices', 'cpu_fpga'}
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
cpu_fpgas = ['0x1000/0x0179', '0x2100/0x0180']
kwargs = {}
kwargs['sleep_flag'] = True
tpm_mock.return_value = False
bios_mock.return_value = 'V4.6.5.4 R1.15.0 for D3099-B1x'
irmc_mock.return_value = 'iRMC S4-7.82F'
server_mock.return_value = 'TX2540M1F5'
pci_device_mock.side_effect = [1, 1]
expected = {'irmc_firmware_version': 'iRMC S4-7.82F',
'pci_gpu_devices': 1,
'cpu_fpga': 1,
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
'server_model': 'TX2540M1F5',
'trusted_boot': False}
result = scci.get_capabilities_properties(
self.irmc_info,
capabilities_properties,
gpu_ids,
cpu_fpgas,
**kwargs)
self.assertEqual(expected, result)
tpm_mock.assert_called_once_with(self.irmc_info)
bios_mock.assert_called_once_with(mock.ANY)
irmc_mock.assert_called_once_with(mock.ANY)
server_mock.assert_called_once_with(mock.ANY)
pci_device_mock.assert_has_calls([
mock.call(self.irmc_info, gpu_ids),
mock.call(self.irmc_info, cpu_fpgas)])
@mock.patch.object(ipmi, 'get_pci_device')
@mock.patch.object(snmp, 'get_server_model') @mock.patch.object(snmp, 'get_server_model')
@mock.patch.object(snmp, 'get_irmc_firmware_version') @mock.patch.object(snmp, 'get_irmc_firmware_version')
@mock.patch.object(snmp, 'get_bios_firmware_version') @mock.patch.object(snmp, 'get_bios_firmware_version')
@@ -758,10 +805,11 @@ class SCCITestCase(testtools.TestCase):
bios_mock, bios_mock,
irmc_mock, irmc_mock,
server_mock, server_mock,
gpu_mock): pci_device_mock):
capabilities_properties = {} capabilities_properties = {}
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080'] gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
cpu_fpgas = ['0x1000/0x0179', '0x2100/0x0180']
kwargs = {} kwargs = {}
kwargs['sleep_flag'] = True kwargs['sleep_flag'] = True
@@ -769,7 +817,7 @@ class SCCITestCase(testtools.TestCase):
bios_mock.return_value = 'V4.6.5.4 R1.15.0 for D3099-B1x' bios_mock.return_value = 'V4.6.5.4 R1.15.0 for D3099-B1x'
irmc_mock.return_value = 'iRMC S4-7.82F' irmc_mock.return_value = 'iRMC S4-7.82F'
server_mock.return_value = 'TX2540M1F5' server_mock.return_value = 'TX2540M1F5'
gpu_mock.return_value = 1 pci_device_mock.side_effect = [1, 1]
expected = {} expected = {}
@@ -777,6 +825,7 @@ class SCCITestCase(testtools.TestCase):
self.irmc_info, self.irmc_info,
capabilities_properties, capabilities_properties,
gpu_ids, gpu_ids,
cpu_fpgas,
**kwargs) **kwargs)
self.assertEqual(expected, result) self.assertEqual(expected, result)
@@ -788,8 +837,9 @@ class SCCITestCase(testtools.TestCase):
ipmiraw_mock): ipmiraw_mock):
capabilities_properties = {'trusted_boot', 'irmc_firmware_version', capabilities_properties = {'trusted_boot', 'irmc_firmware_version',
'rom_firmware_version', 'server_model', 'rom_firmware_version', 'server_model',
'pci_gpu_devices'} 'pci_gpu_devices', 'cpu_fpga'}
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080'] gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
cpu_fpgas = ['0x1000/0x0179', '0x2100/0x0180']
kwargs = {} kwargs = {}
kwargs['sleep_flag'] = True kwargs['sleep_flag'] = True
@@ -801,19 +851,21 @@ class SCCITestCase(testtools.TestCase):
self.irmc_info, self.irmc_info,
capabilities_properties, capabilities_properties,
gpu_ids, gpu_ids,
cpu_fpgas,
**kwargs) **kwargs)
self.assertEqual('Capabilities inspection failed: SNMP operation \'' self.assertEqual('Capabilities inspection failed: SNMP operation \''
'GET BIOS FIRMWARE VERSION\' failed: error', str(e)) 'GET BIOS FIRMWARE VERSION\' failed: error', str(e))
@mock.patch.object(ipmi, 'get_gpu') @mock.patch.object(ipmi, 'get_pci_device')
@mock.patch.object(snmp.SNMPClient, 'get') @mock.patch.object(snmp.SNMPClient, 'get')
def test_get_capabilities_properties_scci_client_error_ipmi(self, def test_get_capabilities_properties_scci_client_error_ipmi(self,
snmp_mock, snmp_mock,
ipmi_mock): ipmi_mock):
capabilities_properties = {'trusted_boot', 'irmc_firmware_version', capabilities_properties = {'trusted_boot', 'irmc_firmware_version',
'rom_firmware_version', 'server_model', 'rom_firmware_version', 'server_model',
'pci_gpu_devices'} 'pci_gpu_devices', 'cpu_fpga'}
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080'] gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
cpu_fpgas = ['0x1000/0x0179', '0x2100/0x0180']
kwargs = {} kwargs = {}
kwargs['sleep_flag'] = True kwargs['sleep_flag'] = True
@@ -825,5 +877,6 @@ class SCCITestCase(testtools.TestCase):
self.irmc_info, self.irmc_info,
capabilities_properties, capabilities_properties,
gpu_ids, gpu_ids,
cpu_fpgas,
**kwargs) **kwargs)
self.assertEqual('Capabilities inspection failed: IPMI error', str(e)) self.assertEqual('Capabilities inspection failed: IPMI error', str(e))