diff options
| -rwxr-xr-x | cloudinit/sources/DataSourceAzure.py | 49 | ||||
| -rw-r--r-- | tests/unittests/test_datasource/test_azure.py | 34 | 
2 files changed, 56 insertions, 27 deletions
| diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 44cca210..87a848ce 100755 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -1321,36 +1321,35 @@ def parse_network_config(imds_metadata):              LOG.debug('Azure: generating network configuration from IMDS')              network_metadata = imds_metadata['network']              for idx, intf in enumerate(network_metadata['interface']): +                # First IPv4 and/or IPv6 address will be obtained via DHCP. +                # Any additional IPs of each type will be set as static +                # addresses.                  nicname = 'eth{idx}'.format(idx=idx) -                dev_config = {'dhcp4': False, 'dhcp6': False}                  dhcp_override = {'route-metric': (idx + 1) * 100} -                for addr4 in intf['ipv4']['ipAddress']: -                    privateIpv4 = addr4['privateIpAddress'] -                    if privateIpv4: -                        if dev_config.get('dhcp4', False): -                            # Append static address config for ip > 1 -                            netPrefix = intf['ipv4']['subnet'][0].get( -                                'prefix', '24') -                            if not dev_config.get('addresses'): -                                dev_config['addresses'] = [] -                            dev_config['addresses'].append( -                                '{ip}/{prefix}'.format( -                                    ip=privateIpv4, prefix=netPrefix)) -                        else: -                            dev_config['dhcp4'] = True +                dev_config = {'dhcp4': True, 'dhcp4-overrides': dhcp_override, +                              'dhcp6': False} +                for addr_type in ('ipv4', 'ipv6'): +                    addresses = intf.get(addr_type, {}).get('ipAddress', []) +                    if addr_type == 'ipv4': +                        default_prefix = '24' +                    else: +                        default_prefix = '128' +                        if addresses: +                            dev_config['dhcp6'] = True                              # non-primary interfaces should have a higher                              # route-metric (cost) so default routes prefer                              # primary nic due to lower route-metric value -                            dev_config['dhcp4-overrides'] = dhcp_override -                for addr6 in intf['ipv6']['ipAddress']: -                    privateIpv6 = addr6['privateIpAddress'] -                    if privateIpv6: -                        dev_config['dhcp6'] = True -                        # non-primary interfaces should have a higher -                        # route-metric (cost) so default routes prefer -                        # primary nic due to lower route-metric value -                        dev_config['dhcp6-overrides'] = dhcp_override -                        break +                            dev_config['dhcp6-overrides'] = dhcp_override +                    for addr in addresses[1:]: +                        # Append static address config for ip > 1 +                        netPrefix = intf[addr_type]['subnet'][0].get( +                            'prefix', default_prefix) +                        privateIp = addr['privateIpAddress'] +                        if not dev_config.get('addresses'): +                            dev_config['addresses'] = [] +                        dev_config['addresses'].append( +                            '{ip}/{prefix}'.format( +                                ip=privateIp, prefix=netPrefix))                  if dev_config:                      mac = ':'.join(re.findall(r'..', intf['macAddress']))                      dev_config.update( diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py index d92d7b2f..59e351de 100644 --- a/tests/unittests/test_datasource/test_azure.py +++ b/tests/unittests/test_datasource/test_azure.py @@ -197,9 +197,11 @@ class TestParseNetworkConfig(CiTestCase):      def test_ipv4_and_ipv6_route_metrics_match_for_nics(self):          """parse_network_config emits matching ipv4 and ipv6 route-metrics."""          expected = {'ethernets': { -            'eth0': {'dhcp4': True, +            'eth0': {'addresses': ['10.0.0.5/24', '2001:dead:beef::2/128'], +                     'dhcp4': True,                       'dhcp4-overrides': {'route-metric': 100}, -                     'dhcp6': False, +                     'dhcp6': True, +                     'dhcp6-overrides': {'route-metric': 100},                       'match': {'macaddress': '00:0d:3a:04:75:98'},                       'set-name': 'eth0'},              'eth1': {'set-name': 'eth1', @@ -214,6 +216,14 @@ class TestParseNetworkConfig(CiTestCase):                       'dhcp6': True,                       'dhcp6-overrides': {'route-metric': 300}}}, 'version': 2}          imds_data = copy.deepcopy(NETWORK_METADATA) +        nic1 = imds_data['network']['interface'][0] +        nic1['ipv4']['ipAddress'].append({'privateIpAddress': '10.0.0.5'}) + +        nic1['ipv6'] = { +            "subnet": [{"address": "2001:dead:beef::16"}], +            "ipAddress": [{"privateIpAddress": "2001:dead:beef::1"}, +                          {"privateIpAddress": "2001:dead:beef::2"}] +        }          imds_data['network']['interface'].append(SECONDARY_INTERFACE)          third_intf = copy.deepcopy(SECONDARY_INTERFACE)          third_intf['macAddress'] = third_intf['macAddress'].replace('22', '33') @@ -240,6 +250,26 @@ class TestParseNetworkConfig(CiTestCase):          nic1 = imds_data['network']['interface'][0]          nic1['ipv4']['ipAddress'].append({'privateIpAddress': '10.0.0.5'}) +        nic1['ipv6'] = { +            "subnet": [{"prefix": "10", "address": "2001:dead:beef::16"}], +            "ipAddress": [{"privateIpAddress": "2001:dead:beef::1"}] +        } +        self.assertEqual(expected, dsaz.parse_network_config(imds_data)) + +    def test_ipv6_secondary_ips_will_be_static_cidrs(self): +        """parse_network_config emits primary ipv6 as dhcp others are static""" +        expected = {'ethernets': { +            'eth0': {'addresses': ['10.0.0.5/24', '2001:dead:beef::2/10'], +                     'dhcp4': True, +                     'dhcp4-overrides': {'route-metric': 100}, +                     'dhcp6': True, +                     'dhcp6-overrides': {'route-metric': 100}, +                     'match': {'macaddress': '00:0d:3a:04:75:98'}, +                     'set-name': 'eth0'}}, 'version': 2} +        imds_data = copy.deepcopy(NETWORK_METADATA) +        nic1 = imds_data['network']['interface'][0] +        nic1['ipv4']['ipAddress'].append({'privateIpAddress': '10.0.0.5'}) +          # Secondary ipv6 addresses currently ignored/unconfigured          nic1['ipv6'] = {              "subnet": [{"prefix": "10", "address": "2001:dead:beef::16"}], | 
