Collect IPv6 address during introspection
This patch adds support to retrieve IPv6 address. A new field ``ipv6_address`` is added to NetworkInterface and store the assigned IPv6 address (if any). Co-Authored-By: Kaifeng Wang <kaifeng.w@gmail.com> Change-Id: Ia527a5aa48e3daf66d2be190e43935b38b3bd6f9 Closes-Bug: #1744064 Story: #1744064 Task: #11604
This commit is contained in:
		@@ -260,15 +260,17 @@ class BlockDevice(encoding.SerializableComparable):
 | 
			
		||||
 | 
			
		||||
class NetworkInterface(encoding.SerializableComparable):
 | 
			
		||||
    serializable_fields = ('name', 'mac_address', 'ipv4_address',
 | 
			
		||||
                           'has_carrier', 'lldp', 'vendor', 'product',
 | 
			
		||||
                           'client_id', 'biosdevname')
 | 
			
		||||
                           'ipv6_address', 'has_carrier', 'lldp',
 | 
			
		||||
                           'vendor', 'product', 'client_id',
 | 
			
		||||
                           'biosdevname')
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name, mac_addr, ipv4_address=None, has_carrier=True,
 | 
			
		||||
                 lldp=None, vendor=None, product=None, client_id=None,
 | 
			
		||||
                 biosdevname=None):
 | 
			
		||||
    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):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.mac_address = mac_addr
 | 
			
		||||
        self.ipv4_address = ipv4_address
 | 
			
		||||
        self.ipv6_address = ipv6_address
 | 
			
		||||
        self.has_carrier = has_carrier
 | 
			
		||||
        self.lldp = lldp
 | 
			
		||||
        self.vendor = vendor
 | 
			
		||||
@@ -582,6 +584,7 @@ class GenericHardwareManager(HardwareManager):
 | 
			
		||||
        return NetworkInterface(
 | 
			
		||||
            interface_name, mac_addr,
 | 
			
		||||
            ipv4_address=self.get_ipv4_addr(interface_name),
 | 
			
		||||
            ipv6_address=self.get_ipv6_addr(interface_name),
 | 
			
		||||
            has_carrier=netutils.interface_has_carrier(interface_name),
 | 
			
		||||
            vendor=_get_device_info(interface_name, 'net', 'vendor'),
 | 
			
		||||
            product=_get_device_info(interface_name, 'net', 'device'),
 | 
			
		||||
@@ -590,6 +593,14 @@ class GenericHardwareManager(HardwareManager):
 | 
			
		||||
    def get_ipv4_addr(self, interface_id):
 | 
			
		||||
        return netutils.get_ipv4_addr(interface_id)
 | 
			
		||||
 | 
			
		||||
    def get_ipv6_addr(self, interface_id):
 | 
			
		||||
        """Get the default IPv6 address assigned to the interface.
 | 
			
		||||
 | 
			
		||||
        With different networking environment, the address could be a
 | 
			
		||||
        link-local address, ULA or something else.
 | 
			
		||||
        """
 | 
			
		||||
        return netutils.get_ipv6_addr(interface_id)
 | 
			
		||||
 | 
			
		||||
    def get_bios_given_nic_name(self, interface_name):
 | 
			
		||||
        """Collect the BIOS given NICs name.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -203,15 +203,24 @@ def _get_lldp_info(interfaces):
 | 
			
		||||
    return lldp_info
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_ipv4_addr(interface_id):
 | 
			
		||||
def get_default_ip_addr(type, interface_id):
 | 
			
		||||
    """Retrieve default IPv4 or IPv6 address."""
 | 
			
		||||
    try:
 | 
			
		||||
        addrs = netifaces.ifaddresses(interface_id)
 | 
			
		||||
        return addrs[netifaces.AF_INET][0]['addr']
 | 
			
		||||
        return addrs[type][0]['addr']
 | 
			
		||||
    except (ValueError, IndexError, KeyError):
 | 
			
		||||
        # No default IPv4 address found
 | 
			
		||||
        # No default IP address found
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_ipv4_addr(interface_id):
 | 
			
		||||
    return get_default_ip_addr(netifaces.AF_INET, interface_id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_ipv6_addr(interface_id):
 | 
			
		||||
    return get_default_ip_addr(netifaces.AF_INET6, interface_id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_mac_addr(interface_id):
 | 
			
		||||
    try:
 | 
			
		||||
        addrs = netifaces.ifaddresses(interface_id)
 | 
			
		||||
 
 | 
			
		||||
@@ -513,7 +513,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        read_mock = mocked_open.return_value.read
 | 
			
		||||
        read_mock.side_effect = ['1']
 | 
			
		||||
        mocked_ifaddresses.return_value = {
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}]
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}],
 | 
			
		||||
            netifaces.AF_INET6: [{'addr': 'fd00::101'}]
 | 
			
		||||
        }
 | 
			
		||||
        mocked_execute.return_value = ('em0\n', '')
 | 
			
		||||
        mock_get_mac.mock_has_carrier = True
 | 
			
		||||
@@ -523,6 +524,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        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)
 | 
			
		||||
@@ -552,7 +554,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        read_mock = mocked_open.return_value.read
 | 
			
		||||
        read_mock.side_effect = ['1']
 | 
			
		||||
        mocked_ifaddresses.return_value = {
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}]
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}],
 | 
			
		||||
            netifaces.AF_INET6: [{'addr': 'fd00::101'}]
 | 
			
		||||
        }
 | 
			
		||||
        mocked_execute.return_value = ('em0\n', '')
 | 
			
		||||
        mock_get_mac.return_value = '00:0c:29:8c:11:b1'
 | 
			
		||||
@@ -562,6 +565,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        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)
 | 
			
		||||
@@ -645,7 +649,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        read_mock = mocked_open.return_value.read
 | 
			
		||||
        read_mock.side_effect = ['1']
 | 
			
		||||
        mocked_ifaddresses.return_value = {
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}]
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}],
 | 
			
		||||
            netifaces.AF_INET6: [{'addr': 'fd00::101'}]
 | 
			
		||||
        }
 | 
			
		||||
        mocked_lldp_info.return_value = {'eth0': [
 | 
			
		||||
            (0, b''),
 | 
			
		||||
@@ -661,6 +666,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        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)
 | 
			
		||||
        expected_lldp_info = [
 | 
			
		||||
            (0, ''),
 | 
			
		||||
            (1, '04885a92ec5459'),
 | 
			
		||||
@@ -693,7 +699,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        read_mock = mocked_open.return_value.read
 | 
			
		||||
        read_mock.side_effect = ['1']
 | 
			
		||||
        mocked_ifaddresses.return_value = {
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}]
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}],
 | 
			
		||||
            netifaces.AF_INET6: [{'addr': 'fd00::101'}]
 | 
			
		||||
        }
 | 
			
		||||
        mocked_lldp_info.side_effect = Exception('Boom!')
 | 
			
		||||
        mocked_execute.return_value = ('em0\n', '')
 | 
			
		||||
@@ -704,6 +711,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        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)
 | 
			
		||||
@@ -734,7 +742,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        read_mock = mocked_open.return_value.read
 | 
			
		||||
        read_mock.side_effect = [OSError('boom')]
 | 
			
		||||
        mocked_ifaddresses.return_value = {
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}]
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}],
 | 
			
		||||
            netifaces.AF_INET6: [{'addr': 'fd00::101'}]
 | 
			
		||||
        }
 | 
			
		||||
        mocked_execute.return_value = ('em0\n', '')
 | 
			
		||||
        mock_has_carrier.return_value = False
 | 
			
		||||
@@ -744,6 +753,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        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.assertFalse(interfaces[0].has_carrier)
 | 
			
		||||
        self.assertIsNone(interfaces[0].vendor)
 | 
			
		||||
        self.assertEqual('em0', interfaces[0].biosdevname)
 | 
			
		||||
@@ -774,7 +784,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        mac = '00:0c:29:8c:11:b1'
 | 
			
		||||
        read_mock.side_effect = ['0x15b3\n', '0x1014\n']
 | 
			
		||||
        mocked_ifaddresses.return_value = {
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}]
 | 
			
		||||
            netifaces.AF_INET: [{'addr': '192.168.1.2'}],
 | 
			
		||||
            netifaces.AF_INET6: [{'addr': 'fd00::101'}]
 | 
			
		||||
        }
 | 
			
		||||
        mocked_execute.return_value = ('em0\n', '')
 | 
			
		||||
        mock_has_carrier.return_value = True
 | 
			
		||||
@@ -784,6 +795,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
 | 
			
		||||
        self.assertEqual('eth0', interfaces[0].name)
 | 
			
		||||
        self.assertEqual(mac, interfaces[0].mac_address)
 | 
			
		||||
        self.assertEqual('192.168.1.2', interfaces[0].ipv4_address)
 | 
			
		||||
        self.assertEqual('fd00::101', interfaces[0].ipv6_address)
 | 
			
		||||
        self.assertTrue(interfaces[0].has_carrier)
 | 
			
		||||
        self.assertEqual('0x15b3', interfaces[0].vendor)
 | 
			
		||||
        self.assertEqual('0x1014', interfaces[0].product)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
---
 | 
			
		||||
fixes:
 | 
			
		||||
  - Adds support to collect the default IPv6 address for interfaces. With
 | 
			
		||||
    different networking environment, the address could be a link-local
 | 
			
		||||
    address, ULA or something else.
 | 
			
		||||
		Reference in New Issue
	
	Block a user