Add PCI devices collector to inspector
Adds a new collector, which gathers list of PCI devices. Each entry is a dictionary containing 2 keys: - vendor-id - product-id Such information can then be used by the inspector to distinguish appropriate PCI devices. Change-Id: Id7521d66410e7d408d7eada692b6123e769ce084 Partial-Bug: #1580893
This commit is contained in:
parent
0c5a1cfd56
commit
f7e080c8bf
@ -16,6 +16,7 @@
|
|||||||
import base64
|
import base64
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import tarfile
|
import tarfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -381,3 +382,52 @@ def collect_extra_hardware(data, failures):
|
|||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
msg = 'JSON returned from hardware-detect cannot be decoded: %s'
|
msg = 'JSON returned from hardware-detect cannot be decoded: %s'
|
||||||
failures.add(msg, exc)
|
failures.add(msg, exc)
|
||||||
|
|
||||||
|
|
||||||
|
def collect_pci_devices_info(data, failures):
|
||||||
|
"""Collect a list of PCI devices.
|
||||||
|
|
||||||
|
Each PCI device entry in list is a dictionary containing vendor_id and
|
||||||
|
product_id keys, which will be then used by the ironic inspector to
|
||||||
|
distinguish various PCI devices.
|
||||||
|
|
||||||
|
The data is gathered from /sys/bus/pci/devices directory.
|
||||||
|
|
||||||
|
:param data: mutable data that we'll send to inspector
|
||||||
|
:param failures: AccumulatedFailures object
|
||||||
|
"""
|
||||||
|
pci_devices_path = '/sys/bus/pci/devices'
|
||||||
|
pci_devices_info = []
|
||||||
|
try:
|
||||||
|
subdirs = os.listdir(pci_devices_path)
|
||||||
|
except OSError as exc:
|
||||||
|
msg = 'Failed to get list of PCI devices: %s'
|
||||||
|
failures.add(msg, exc)
|
||||||
|
return
|
||||||
|
for subdir in subdirs:
|
||||||
|
if not os.path.isdir(os.path.join(pci_devices_path, subdir)):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
# note(sborkows): ids located in files inside PCI devices
|
||||||
|
# directory are stored in hex format (0x1234 for example) and
|
||||||
|
# we only need that part after 'x' delimiter
|
||||||
|
with open(os.path.join(pci_devices_path, subdir,
|
||||||
|
'vendor')) as vendor_file:
|
||||||
|
vendor = vendor_file.read().strip().split('x')[1]
|
||||||
|
with open(os.path.join(pci_devices_path, subdir,
|
||||||
|
'device')) as vendor_device:
|
||||||
|
device = vendor_device.read().strip().split('x')[1]
|
||||||
|
except IOError as exc:
|
||||||
|
LOG.warning('Failed to gather vendor id or product id '
|
||||||
|
'from PCI device %s: %s', subdir, exc)
|
||||||
|
continue
|
||||||
|
except IndexError as exc:
|
||||||
|
LOG.warning('Wrong format of vendor id or product id in PCI '
|
||||||
|
'device %s: %s', subdir, exc)
|
||||||
|
continue
|
||||||
|
LOG.debug(
|
||||||
|
'Found a PCI device with vendor id %s and product id %s',
|
||||||
|
vendor, device)
|
||||||
|
pci_devices_info.append({'vendor_id': vendor,
|
||||||
|
'product_id': device})
|
||||||
|
data['pci_devices'] = pci_devices_info
|
||||||
|
@ -17,6 +17,7 @@ import base64
|
|||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import io
|
import io
|
||||||
|
import os
|
||||||
import tarfile
|
import tarfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -461,6 +462,60 @@ class TestCollectExtraHardware(test_base.BaseTestCase):
|
|||||||
mock_execute.assert_called_once_with('hardware-detect')
|
mock_execute.assert_called_once_with('hardware-detect')
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch.object(os, 'listdir', autospec=True)
|
||||||
|
class TestCollectPciDevicesInfo(test_base.BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestCollectPciDevicesInfo, self).setUp()
|
||||||
|
self.data = {}
|
||||||
|
self.failures = utils.AccumulatedFailures()
|
||||||
|
|
||||||
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
||||||
|
def test_success(self, mock_isdir, mock_listdir):
|
||||||
|
subdirs = ['foo', 'bar']
|
||||||
|
mock_listdir.return_value = subdirs
|
||||||
|
mock_isdir.return_value = True
|
||||||
|
reads = ['0x1234', '0x5678', '0x9876', '0x5432']
|
||||||
|
expected_pci_devices = [{'vendor_id': '1234', 'product_id': '5678'},
|
||||||
|
{'vendor_id': '9876', 'product_id': '5432'}]
|
||||||
|
|
||||||
|
mock_open = mock.mock_open()
|
||||||
|
with mock.patch('six.moves.builtins.open', mock_open):
|
||||||
|
mock_read = mock_open.return_value.read
|
||||||
|
mock_read.side_effect = reads
|
||||||
|
inspector.collect_pci_devices_info(self.data, self.failures)
|
||||||
|
|
||||||
|
self.assertEqual(2 * len(subdirs), mock_open.call_count)
|
||||||
|
self.assertListEqual(expected_pci_devices, self.data['pci_devices'])
|
||||||
|
|
||||||
|
def test_wrong_path(self, mock_listdir):
|
||||||
|
mock_listdir.side_effect = OSError()
|
||||||
|
|
||||||
|
inspector.collect_pci_devices_info(self.data, self.failures)
|
||||||
|
|
||||||
|
self.assertFalse('pci_devices' in self.data)
|
||||||
|
self.assertEqual(1, len(self.failures._failures))
|
||||||
|
|
||||||
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
||||||
|
def test_bad_pci_device_info(self, mock_isdir, mock_listdir):
|
||||||
|
subdirs = ['foo', 'bar', 'baz']
|
||||||
|
mock_listdir.return_value = subdirs
|
||||||
|
mock_isdir.return_value = True
|
||||||
|
reads = ['0x1234', '0x5678', '0x9876', IOError, IndexError,
|
||||||
|
'0x5432']
|
||||||
|
expected_pci_devices = [{'vendor_id': '1234', 'product_id': '5678'}]
|
||||||
|
|
||||||
|
mock_open = mock.mock_open()
|
||||||
|
with mock.patch('six.moves.builtins.open', mock_open):
|
||||||
|
mock_read = mock_open.return_value.read
|
||||||
|
mock_read.side_effect = reads
|
||||||
|
inspector.collect_pci_devices_info(self.data, self.failures)
|
||||||
|
|
||||||
|
# note(sborkows): due to throwing IOError, the corresponding mock_open
|
||||||
|
# will not be called, so there are 5 mock_open calls in total
|
||||||
|
self.assertEqual(5, mock_open.call_count)
|
||||||
|
self.assertListEqual(expected_pci_devices, self.data['pci_devices'])
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'get_agent_params', lambda: {'BOOTIF': '01-cdef'})
|
@mock.patch.object(utils, 'get_agent_params', lambda: {'BOOTIF': '01-cdef'})
|
||||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||||
class TestWaitForDhcp(test_base.BaseTestCase):
|
class TestWaitForDhcp(test_base.BaseTestCase):
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Adds new PCI devices collector named "pci_devices"
|
||||||
|
to inspector module.
|
||||||
|
Data is gathered from /sys/bus/pci/devices directory
|
||||||
|
and is stored under "pci_devices" key as a dictionary
|
||||||
|
containing "vendor_id" and "product_id" keys, which
|
||||||
|
then will be used by the inspector to distinguish
|
||||||
|
various PCI devices.
|
@ -33,6 +33,7 @@ ironic_python_agent.inspector.collectors =
|
|||||||
default = ironic_python_agent.inspector:collect_default
|
default = ironic_python_agent.inspector:collect_default
|
||||||
logs = ironic_python_agent.inspector:collect_logs
|
logs = ironic_python_agent.inspector:collect_logs
|
||||||
extra-hardware = ironic_python_agent.inspector:collect_extra_hardware
|
extra-hardware = ironic_python_agent.inspector:collect_extra_hardware
|
||||||
|
pci-devices = ironic_python_agent.inspector:collect_pci_devices_info
|
||||||
|
|
||||||
[pbr]
|
[pbr]
|
||||||
autodoc_index_modules = True
|
autodoc_index_modules = True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user