Collect bus and driver for interfaces
It's useful to have pci bus address/driver collected, the operator can use the information to configure portgroup in a consistent way. Change-Id: I432bca881ad881bae6d5e67c9b6fb52fe55b4e1e
This commit is contained in:
@@ -822,11 +822,13 @@ class NetworkInterface(encoding.SerializableComparable):
|
||||
serializable_fields = ('name', 'mac_address', 'ipv4_address',
|
||||
'ipv6_address', 'has_carrier', 'lldp',
|
||||
'vendor', 'product', 'client_id',
|
||||
'biosdevname', 'speed_mbps')
|
||||
'biosdevname', 'speed_mbps', 'pci_address',
|
||||
'driver')
|
||||
|
||||
def __init__(self, name, mac_addr, ipv4_address=None, ipv6_address=None,
|
||||
has_carrier=True, lldp=None, vendor=None, product=None,
|
||||
client_id=None, biosdevname=None, speed_mbps=None):
|
||||
client_id=None, biosdevname=None, speed_mbps=None,
|
||||
pci_address=None, driver=None):
|
||||
self.name = name
|
||||
self.mac_address = mac_addr
|
||||
self.ipv4_address = ipv4_address
|
||||
@@ -837,6 +839,8 @@ class NetworkInterface(encoding.SerializableComparable):
|
||||
self.product = product
|
||||
self.biosdevname = biosdevname
|
||||
self.speed_mbps = speed_mbps
|
||||
self.pci_address = pci_address
|
||||
self.driver = driver
|
||||
# client_id is used for InfiniBand only. we calculate the DHCP
|
||||
# client identifier Option to allow DHCP to work over InfiniBand.
|
||||
# see https://tools.ietf.org/html/rfc4390
|
||||
@@ -1469,7 +1473,10 @@ class GenericHardwareManager(HardwareManager):
|
||||
vendor=_get_device_info(interface_name, 'net', 'vendor'),
|
||||
product=_get_device_info(interface_name, 'net', 'device'),
|
||||
biosdevname=self.get_bios_given_nic_name(interface_name),
|
||||
speed_mbps=self._get_network_speed(interface_name))
|
||||
speed_mbps=self._get_network_speed(interface_name),
|
||||
pci_address=netutils.get_interface_pci_address(interface_name),
|
||||
driver=netutils.get_interface_driver(interface_name)
|
||||
)
|
||||
|
||||
def get_ipv4_addr(self, interface_id):
|
||||
return netutils.get_ipv4_addr(interface_id)
|
||||
|
@@ -280,6 +280,24 @@ def interface_has_carrier(interface_name):
|
||||
return False
|
||||
|
||||
|
||||
def get_interface_pci_address(interface_name):
|
||||
path = '/sys/class/net/{}/device'.format(interface_name)
|
||||
try:
|
||||
return os.path.basename(os.readlink(path))
|
||||
except FileNotFoundError:
|
||||
LOG.debug('No bus address found for interface %s',
|
||||
interface_name)
|
||||
|
||||
|
||||
def get_interface_driver(interface_name):
|
||||
path = '/sys/class/net/{}/device/driver'.format(interface_name)
|
||||
try:
|
||||
return os.path.basename(os.readlink(path))
|
||||
except FileNotFoundError:
|
||||
LOG.debug('No driver found for interface %s',
|
||||
interface_name)
|
||||
|
||||
|
||||
def wrap_ipv6(ip):
|
||||
if netutils.is_valid_ipv6(ip):
|
||||
return "[%s]" % ip
|
||||
|
@@ -6597,6 +6597,54 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
|
||||
self.assertTrue(interfaces[0].has_carrier)
|
||||
self.assertEqual('', interfaces[0].biosdevname)
|
||||
|
||||
@mock.patch.object(netutils, 'get_interface_driver', autospec=True)
|
||||
@mock.patch.object(netutils, 'get_interface_pci_address', autospec=True)
|
||||
def test_list_network_interfaces_with_pci_address(self,
|
||||
mock_get_pci,
|
||||
mock_get_driver,
|
||||
mock_has_carrier,
|
||||
mocked_execute,
|
||||
mocked_open,
|
||||
mocked_exists,
|
||||
mocked_listdir,
|
||||
mocked_net_if_addrs,
|
||||
mockedget_managers,
|
||||
mocked_lshw):
|
||||
mocked_listdir.return_value = ['lo', 'eth0']
|
||||
mocked_exists.side_effect = [False, False, True]
|
||||
mocked_open.return_value.__enter__ = lambda s: s
|
||||
mocked_open.return_value.__exit__ = mock.Mock()
|
||||
read_mock = mocked_open.return_value.read
|
||||
read_mock.side_effect = ['1']
|
||||
mocked_net_if_addrs.return_value = {
|
||||
'lo': [
|
||||
FakeAddr(socket.AF_INET, '127.0.0.1'),
|
||||
FakeAddr(socket.AF_INET6, '::1'),
|
||||
FakeAddr(socket.AF_PACKET, '00:00:00:00:00:00')
|
||||
],
|
||||
'eth0': [
|
||||
FakeAddr(socket.AF_INET, '192.168.1.2'),
|
||||
FakeAddr(socket.AF_INET6, 'fd00::101'),
|
||||
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
|
||||
]
|
||||
}
|
||||
mocked_execute.return_value = ('em0\n', '')
|
||||
mock_has_carrier.return_value = True
|
||||
mock_get_pci.return_value = '0000:02:00.0'
|
||||
mock_get_driver.return_value = 'e1000e'
|
||||
interfaces = self.hardware.list_network_interfaces()
|
||||
self.assertEqual(1, len(interfaces))
|
||||
self.assertEqual('eth0', interfaces[0].name)
|
||||
self.assertEqual('00:0c:29:8c:11:b1', interfaces[0].mac_address)
|
||||
self.assertEqual('192.168.1.2', interfaces[0].ipv4_address)
|
||||
self.assertEqual('fd00::101', interfaces[0].ipv6_address)
|
||||
self.assertIsNone(interfaces[0].lldp)
|
||||
self.assertTrue(interfaces[0].has_carrier)
|
||||
self.assertEqual('em0', interfaces[0].biosdevname)
|
||||
self.assertIsNone(interfaces[0].speed_mbps)
|
||||
self.assertEqual('0000:02:00.0', interfaces[0].pci_address)
|
||||
self.assertEqual('e1000e', interfaces[0].driver)
|
||||
|
||||
def test_list_network_vlan_interfaces(self,
|
||||
mock_has_carrier,
|
||||
mocked_execute,
|
||||
|
@@ -394,3 +394,27 @@ class TestNetutils(base.IronicAgentTest):
|
||||
def test_wrap_ipv6_with_ipv4(self):
|
||||
res = netutils.wrap_ipv6('1.2.3.4')
|
||||
self.assertEqual('1.2.3.4', res)
|
||||
|
||||
@mock.patch('os.readlink', autospec=True)
|
||||
def test_get_interface_pci_address(self, mock_read):
|
||||
mock_read.return_value = '../../../0000:02:00.0'
|
||||
addr = netutils.get_interface_pci_address('ens160')
|
||||
self.assertEqual('0000:02:00.0', addr)
|
||||
|
||||
@mock.patch('os.readlink', autospec=True)
|
||||
def test_get_interface_pci_address_notfound(self, mock_read):
|
||||
mock_read.side_effect = FileNotFoundError
|
||||
addr = netutils.get_interface_pci_address('ens160')
|
||||
self.assertIsNone(addr)
|
||||
|
||||
@mock.patch('os.readlink', autospec=True)
|
||||
def test_get_interface_driver(self, mock_read):
|
||||
mock_read.return_value = '../../../../bus/pci/drivers/e1000e'
|
||||
addr = netutils.get_interface_driver('ens160')
|
||||
self.assertEqual('e1000e', addr)
|
||||
|
||||
@mock.patch('os.readlink', autospec=True)
|
||||
def test_get_interface_driver_notfound(self, mock_read):
|
||||
mock_read.side_effect = FileNotFoundError
|
||||
driver = netutils.get_interface_driver('ens160')
|
||||
self.assertIsNone(driver)
|
||||
|
@@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support to collect pci address and driver information for interfaces.
|
Reference in New Issue
Block a user