Add vendor, product to interface information
This patch updates the interfaces JSON to include vendor and product u'interfaces': [ { u'mac_address': u'00:0c:29:8c:11:b1', u'name': u'eth0', u'ipv4_address': None, u'switch_chassis_descr': None, u'switch_port_descr': None, u'lldp': None, u'vendor': u'0x15b3', u'product': u'0x1014, }] Co-Authored-By: yogananth subramanian <ysubrama@redhat.com> Closes-Bug: #1611856 Change-Id: I8fa58dde29601abee959f74b69b692ed9eaffb94
This commit is contained in:
parent
9f52f47acd
commit
fe3b630360
@ -118,13 +118,15 @@ fields:
|
|||||||
|
|
||||||
``interfaces``
|
``interfaces``
|
||||||
list of network interfaces with fields: ``name``, ``mac_address``,
|
list of network interfaces with fields: ``name``, ``mac_address``,
|
||||||
``ipv4_address``, ``lldp``. If configuration option ``collect_lldp`` is
|
``ipv4_address``, ``lldp``, ``vendor`` and ``product``.
|
||||||
set to True the ``lldp`` field will be populated by a list of
|
If configuration option ``collect_lldp`` is set to True the ``lldp``
|
||||||
type-length-value (TLV) fields retrieved using the Link Layer Discovery
|
field will be populated by a list of type-length-value (TLV) fields
|
||||||
Protocol (LLDP). Currently IPA also returns 2 fields ``switch_port_descr``
|
retrieved using the Link Layer Discovery Protocol (LLDP).
|
||||||
|
Currently IPA also returns 2 fields ``switch_port_descr``
|
||||||
and ``switch_chassis_descr`` which were reserved for future use, these are
|
and ``switch_chassis_descr`` which were reserved for future use, these are
|
||||||
now deprecated to be removed in Ocata in favor of including all LLDP data
|
now deprecated to be removed in Ocata in favor of including all LLDP data
|
||||||
in the ``lddp`` field.
|
in the ``lldp`` field.
|
||||||
|
|
||||||
|
|
||||||
``system_vendor``
|
``system_vendor``
|
||||||
system vendor information from SMBIOS as reported by ``dmidecode``:
|
system vendor information from SMBIOS as reported by ``dmidecode``:
|
||||||
|
@ -48,14 +48,17 @@ UNIT_CONVERTER.define('GB = 1024 MB')
|
|||||||
NODE = None
|
NODE = None
|
||||||
|
|
||||||
|
|
||||||
def _get_device_vendor(dev):
|
def _get_device_info(dev, devclass, field):
|
||||||
"""Get the vendor name of a given device."""
|
"""Get the device info according to device class and field."""
|
||||||
try:
|
try:
|
||||||
devname = os.path.basename(dev)
|
devname = os.path.basename(dev)
|
||||||
with open('/sys/class/block/%s/device/vendor' % devname, 'r') as f:
|
with open('/sys/class/%s/%s/device/%s' % (devclass, devname, field),
|
||||||
|
'r') as f:
|
||||||
return f.read().strip()
|
return f.read().strip()
|
||||||
except IOError:
|
except IOError:
|
||||||
LOG.warning("Can't find the device vendor for device %s", dev)
|
LOG.warning(
|
||||||
|
"Can't find field {0} for device {1} in device class {2}".format(
|
||||||
|
field, dev, devclass))
|
||||||
|
|
||||||
|
|
||||||
def _udev_settle():
|
def _udev_settle():
|
||||||
@ -157,7 +160,8 @@ def list_all_block_devices(block_type='disk'):
|
|||||||
model=device['MODEL'],
|
model=device['MODEL'],
|
||||||
size=int(device['SIZE']),
|
size=int(device['SIZE']),
|
||||||
rotational=bool(int(device['ROTA'])),
|
rotational=bool(int(device['ROTA'])),
|
||||||
vendor=_get_device_vendor(device['KNAME']),
|
vendor=_get_device_info(device['KNAME'],
|
||||||
|
'block', 'vendor'),
|
||||||
**extra))
|
**extra))
|
||||||
return devices
|
return devices
|
||||||
|
|
||||||
@ -205,15 +209,17 @@ class BlockDevice(encoding.SerializableComparable):
|
|||||||
class NetworkInterface(encoding.SerializableComparable):
|
class NetworkInterface(encoding.SerializableComparable):
|
||||||
serializable_fields = ('name', 'mac_address', 'switch_port_descr',
|
serializable_fields = ('name', 'mac_address', 'switch_port_descr',
|
||||||
'switch_chassis_descr', 'ipv4_address',
|
'switch_chassis_descr', 'ipv4_address',
|
||||||
'has_carrier', 'lldp')
|
'has_carrier', 'lldp', 'vendor', 'product')
|
||||||
|
|
||||||
def __init__(self, name, mac_addr, ipv4_address=None, has_carrier=True,
|
def __init__(self, name, mac_addr, ipv4_address=None, has_carrier=True,
|
||||||
lldp=None):
|
lldp=None, vendor=None, product=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.mac_address = mac_addr
|
self.mac_address = mac_addr
|
||||||
self.ipv4_address = ipv4_address
|
self.ipv4_address = ipv4_address
|
||||||
self.has_carrier = has_carrier
|
self.has_carrier = has_carrier
|
||||||
self.lldp = lldp
|
self.lldp = lldp
|
||||||
|
self.vendor = vendor
|
||||||
|
self.product = product
|
||||||
# TODO(sambetts) Remove these fields in Ocata, they have been
|
# TODO(sambetts) Remove these fields in Ocata, they have been
|
||||||
# superseded by self.lldp
|
# superseded by self.lldp
|
||||||
self.switch_port_descr = None
|
self.switch_port_descr = None
|
||||||
@ -501,7 +507,9 @@ class GenericHardwareManager(HardwareManager):
|
|||||||
interface_name, mac_addr,
|
interface_name, mac_addr,
|
||||||
ipv4_address=self.get_ipv4_addr(interface_name),
|
ipv4_address=self.get_ipv4_addr(interface_name),
|
||||||
has_carrier=self._interface_has_carrier(interface_name),
|
has_carrier=self._interface_has_carrier(interface_name),
|
||||||
lldp=self._get_lldp_data(interface_name))
|
lldp=self._get_lldp_data(interface_name),
|
||||||
|
vendor=_get_device_info(interface_name, 'net', 'vendor'),
|
||||||
|
product=_get_device_info(interface_name, 'net', 'device'))
|
||||||
|
|
||||||
def get_ipv4_addr(self, interface_id):
|
def get_ipv4_addr(self, interface_id):
|
||||||
try:
|
try:
|
||||||
|
@ -423,6 +423,35 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
self.assertEqual('00:0c:29:8c:11:b1', interfaces[0].mac_address)
|
self.assertEqual('00:0c:29:8c:11:b1', interfaces[0].mac_address)
|
||||||
self.assertEqual('192.168.1.2', interfaces[0].ipv4_address)
|
self.assertEqual('192.168.1.2', interfaces[0].ipv4_address)
|
||||||
self.assertFalse(interfaces[0].has_carrier)
|
self.assertFalse(interfaces[0].has_carrier)
|
||||||
|
self.assertIsNone(interfaces[0].vendor)
|
||||||
|
|
||||||
|
@mock.patch('netifaces.ifaddresses')
|
||||||
|
@mock.patch('os.listdir')
|
||||||
|
@mock.patch('os.path.exists')
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_list_network_interfaces_with_vendor_info(self,
|
||||||
|
mocked_open,
|
||||||
|
mocked_exists,
|
||||||
|
mocked_listdir,
|
||||||
|
mocked_ifaddresses):
|
||||||
|
mocked_listdir.return_value = ['lo', 'eth0']
|
||||||
|
mocked_exists.side_effect = [False, True]
|
||||||
|
mocked_open.return_value.__enter__ = lambda s: s
|
||||||
|
mocked_open.return_value.__exit__ = mock.Mock()
|
||||||
|
read_mock = mocked_open.return_value.read
|
||||||
|
mac = '00:0c:29:8c:11:b1'
|
||||||
|
read_mock.side_effect = [mac + '\n', '1', '0x15b3\n', '0x1014\n']
|
||||||
|
mocked_ifaddresses.return_value = {
|
||||||
|
netifaces.AF_INET: [{'addr': '192.168.1.2'}]
|
||||||
|
}
|
||||||
|
interfaces = self.hardware.list_network_interfaces()
|
||||||
|
self.assertEqual(1, len(interfaces))
|
||||||
|
self.assertEqual('eth0', interfaces[0].name)
|
||||||
|
self.assertEqual(mac, interfaces[0].mac_address)
|
||||||
|
self.assertEqual('192.168.1.2', interfaces[0].ipv4_address)
|
||||||
|
self.assertTrue(interfaces[0].has_carrier)
|
||||||
|
self.assertEqual('0x15b3', interfaces[0].vendor)
|
||||||
|
self.assertEqual('0x1014', interfaces[0].product)
|
||||||
|
|
||||||
@mock.patch.object(hardware, 'get_cached_node')
|
@mock.patch.object(hardware, 'get_cached_node')
|
||||||
@mock.patch.object(utils, 'execute')
|
@mock.patch.object(utils, 'execute')
|
||||||
@ -558,11 +587,12 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
mock_cached_node.assert_called_once_with()
|
mock_cached_node.assert_called_once_with()
|
||||||
mock_dev.assert_called_once_with()
|
mock_dev.assert_called_once_with()
|
||||||
|
|
||||||
def test__get_device_vendor(self):
|
def test__get_device_info(self):
|
||||||
fileobj = mock.mock_open(read_data='fake-vendor')
|
fileobj = mock.mock_open(read_data='fake-vendor')
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
'six.moves.builtins.open', fileobj, create=True) as mock_open:
|
'six.moves.builtins.open', fileobj, create=True) as mock_open:
|
||||||
vendor = hardware._get_device_vendor('/dev/sdfake')
|
vendor = hardware._get_device_info(
|
||||||
|
'/dev/sdfake', 'block', 'vendor')
|
||||||
mock_open.assert_called_once_with(
|
mock_open.assert_called_once_with(
|
||||||
'/sys/class/block/sdfake/device/vendor', 'r')
|
'/sys/class/block/sdfake/device/vendor', 'r')
|
||||||
self.assertEqual('fake-vendor', vendor)
|
self.assertEqual('fake-vendor', vendor)
|
||||||
@ -692,7 +722,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
|
|
||||||
list_mock.assert_called_once_with()
|
list_mock.assert_called_once_with()
|
||||||
|
|
||||||
@mock.patch.object(hardware, '_get_device_vendor')
|
@mock.patch.object(hardware, '_get_device_info')
|
||||||
@mock.patch.object(pyudev.Device, 'from_device_file')
|
@mock.patch.object(pyudev.Device, 'from_device_file')
|
||||||
@mock.patch.object(utils, 'execute')
|
@mock.patch.object(utils, 'execute')
|
||||||
def test_list_all_block_device(self, mocked_execute, mocked_udev,
|
def test_list_all_block_device(self, mocked_execute, mocked_udev,
|
||||||
@ -732,7 +762,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
self.assertEqual(getattr(expected, attr),
|
self.assertEqual(getattr(expected, attr),
|
||||||
getattr(device, attr))
|
getattr(device, attr))
|
||||||
|
|
||||||
@mock.patch.object(hardware, '_get_device_vendor')
|
@mock.patch.object(hardware, '_get_device_info')
|
||||||
@mock.patch.object(pyudev.Device, 'from_device_file')
|
@mock.patch.object(pyudev.Device, 'from_device_file')
|
||||||
@mock.patch.object(utils, 'execute')
|
@mock.patch.object(utils, 'execute')
|
||||||
def test_list_all_block_device_udev_17(self, mocked_execute, mocked_udev,
|
def test_list_all_block_device_udev_17(self, mocked_execute, mocked_udev,
|
||||||
@ -744,7 +774,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
devices = hardware.list_all_block_devices()
|
devices = hardware.list_all_block_devices()
|
||||||
self.assertEqual(4, len(devices))
|
self.assertEqual(4, len(devices))
|
||||||
|
|
||||||
@mock.patch.object(hardware, '_get_device_vendor')
|
@mock.patch.object(hardware, '_get_device_info')
|
||||||
@mock.patch.object(pyudev.Device, 'from_device_file')
|
@mock.patch.object(pyudev.Device, 'from_device_file')
|
||||||
@mock.patch.object(utils, 'execute')
|
@mock.patch.object(utils, 'execute')
|
||||||
def test_list_all_block_device_with_udev(self, mocked_execute, mocked_udev,
|
def test_list_all_block_device_with_udev(self, mocked_execute, mocked_udev,
|
||||||
@ -1461,7 +1491,8 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
@mock.patch.object(utils, 'execute', autospec=True)
|
@mock.patch.object(utils, 'execute', autospec=True)
|
||||||
class TestModuleFunctions(test_base.BaseTestCase):
|
class TestModuleFunctions(test_base.BaseTestCase):
|
||||||
|
|
||||||
@mock.patch.object(hardware, '_get_device_vendor', lambda x: "FooTastic")
|
@mock.patch.object(hardware, '_get_device_info',
|
||||||
|
lambda x, y, z: 'FooTastic')
|
||||||
@mock.patch.object(hardware, '_udev_settle', autospec=True)
|
@mock.patch.object(hardware, '_udev_settle', autospec=True)
|
||||||
@mock.patch.object(hardware.pyudev.Device, "from_device_file")
|
@mock.patch.object(hardware.pyudev.Device, "from_device_file")
|
||||||
def test_list_all_block_devices_success(self, mocked_fromdevfile,
|
def test_list_all_block_devices_success(self, mocked_fromdevfile,
|
||||||
@ -1475,7 +1506,8 @@ class TestModuleFunctions(test_base.BaseTestCase):
|
|||||||
self.assertEqual(BLK_DEVICE_TEMPLATE_SMALL_DEVICES, result)
|
self.assertEqual(BLK_DEVICE_TEMPLATE_SMALL_DEVICES, result)
|
||||||
mocked_udev.assert_called_once_with()
|
mocked_udev.assert_called_once_with()
|
||||||
|
|
||||||
@mock.patch.object(hardware, '_get_device_vendor', lambda x: "FooTastic")
|
@mock.patch.object(hardware, '_get_device_info',
|
||||||
|
lambda x, y: "FooTastic")
|
||||||
@mock.patch.object(hardware, '_udev_settle', autospec=True)
|
@mock.patch.object(hardware, '_udev_settle', autospec=True)
|
||||||
def test_list_all_block_devices_wrong_block_type(self, mocked_udev,
|
def test_list_all_block_devices_wrong_block_type(self, mocked_udev,
|
||||||
mocked_execute):
|
mocked_execute):
|
||||||
|
@ -41,11 +41,14 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
|
|||||||
self.api_client = ironic_api_client.APIClient(API_URL, DRIVER)
|
self.api_client = ironic_api_client.APIClient(API_URL, DRIVER)
|
||||||
self.hardware_info = {
|
self.hardware_info = {
|
||||||
'interfaces': [
|
'interfaces': [
|
||||||
hardware.NetworkInterface('eth0', '00:0c:29:8c:11:b1'),
|
hardware.NetworkInterface(
|
||||||
|
'eth0', '00:0c:29:8c:11:b1', vendor='0x15b3',
|
||||||
|
product='0x1014'),
|
||||||
hardware.NetworkInterface(
|
hardware.NetworkInterface(
|
||||||
'eth1', '00:0c:29:8c:11:b2',
|
'eth1', '00:0c:29:8c:11:b2',
|
||||||
lldp=[(1, '04885a92ec5459'),
|
lldp=[(1, '04885a92ec5459'),
|
||||||
(2, '0545746865726e6574312f3138')]),
|
(2, '0545746865726e6574312f3138')],
|
||||||
|
vendor='0x15b3', product='0x1014'),
|
||||||
],
|
],
|
||||||
'cpu': hardware.CPU('Awesome Jay CPU x10 9001', '9001', '10',
|
'cpu': hardware.CPU('Awesome Jay CPU x10 9001', '9001', '10',
|
||||||
'ARMv9'),
|
'ARMv9'),
|
||||||
@ -298,6 +301,8 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
|
|||||||
u'switch_port_descr': None,
|
u'switch_port_descr': None,
|
||||||
u'has_carrier': True,
|
u'has_carrier': True,
|
||||||
u'lldp': None,
|
u'lldp': None,
|
||||||
|
u'vendor': u'0x15b3',
|
||||||
|
u'product': u'0x1014'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
u'mac_address': u'00:0c:29:8c:11:b2',
|
u'mac_address': u'00:0c:29:8c:11:b2',
|
||||||
@ -308,6 +313,8 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
|
|||||||
u'has_carrier': True,
|
u'has_carrier': True,
|
||||||
u'lldp': [[1, u'04885a92ec5459'],
|
u'lldp': [[1, u'04885a92ec5459'],
|
||||||
[2, u'0545746865726e6574312f3138']],
|
[2, u'0545746865726e6574312f3138']],
|
||||||
|
u'vendor': u'0x15b3',
|
||||||
|
u'product': u'0x1014'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
u'cpu': {
|
u'cpu': {
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add 'vendor' and 'product' fields to
|
||||||
|
interfaces data for future use in Ironic Inspector.
|
Loading…
Reference in New Issue
Block a user