cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #02008
[Merge] ~akaris/cloud-init:bug1679817 into cloud-init:master
Andreas Karis has proposed merging ~akaris/cloud-init:bug1679817 into cloud-init:master.
Commit message:
Fix dual stack IPv4/IPv6 configuration for RHEL
Dual stack IPv4/IPv6 configuration via config drive is broken for RHEL7.
This patch fixes several scenarios for IPv4/IPv6/dual stack with multiple IP assignment
Removes unpopular IPv4 alias files and invalid IPv6 alias files
Also fixes associated unit tests
LP: #1679817
LP: #1685534
LP: #1685532
Requested reviews:
cloud init development team (cloud-init-dev)
For more details, see:
https://code.launchpad.net/~akaris/cloud-init/+git/cloud-init/+merge/322998
Fix dual stack IPv4/IPv6 configuration for RHEL
Dual stack IPv4/IPv6 configuration via config drive is broken for RHEL7.
This patch fixes several scenarios for IPv4/IPv6/dual stack with multiple IP assignment
Removes unpopular IPv4 alias files and invalid IPv6 alias files
Also fixes associated unit tests
LP: #1679817
LP: #1685534
LP: #1685532
--
Your team cloud init development team is requested to review the proposed merge of ~akaris/cloud-init:bug1679817 into cloud-init:master.
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 504e4d0..babc5cd 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -59,6 +59,9 @@ class ConfigMap(object):
def __setitem__(self, key, value):
self._conf[key] = value
+ def __getitem__(self, key):
+ return self._conf[key]
+
def drop(self, key):
self._conf.pop(key, None)
@@ -211,27 +214,67 @@ class Renderer(renderer.Renderer):
iface_cfg[new_key] = old_value
@classmethod
- def _render_subnet(cls, iface_cfg, route_cfg, subnet):
- subnet_type = subnet.get('type')
- if subnet_type == 'dhcp6':
- iface_cfg['DHCPV6C'] = True
- iface_cfg['IPV6INIT'] = True
- iface_cfg['BOOTPROTO'] = 'dhcp'
- elif subnet_type in ['dhcp4', 'dhcp']:
- iface_cfg['BOOTPROTO'] = 'dhcp'
- elif subnet_type == 'static':
- iface_cfg['BOOTPROTO'] = 'static'
- if subnet_is_ipv6(subnet):
- iface_cfg['IPV6ADDR'] = subnet['address']
+ def _render_subnets(cls, iface_cfg, subnets):
+ # setting base values
+ # iface_cfg['DHCPV6C'] = False
+ # iface_cfg['IPV6INIT'] = False
+ iface_cfg['BOOTPROTO'] = 'none'
+
+ # modifying base values according to subnets
+ for i, subnet in enumerate(subnets,start=len(iface_cfg.children)):
+ subnet_type = subnet.get('type')
+ if subnet_type == 'dhcp6':
iface_cfg['IPV6INIT'] = True
+ iface_cfg['DHCPV6C'] = True
+ iface_cfg['BOOTPROTO'] = 'dhcp'
+ elif subnet_type in ['dhcp4', 'dhcp']:
+ iface_cfg['BOOTPROTO'] = 'dhcp'
+ elif subnet_type == 'static':
+ if iface_cfg['BOOTPROTO'] == 'none':
+ iface_cfg['BOOTPROTO'] = 'static'
+ if subnet_is_ipv6(subnet):
+ iface_cfg['IPV6INIT'] = True
else:
- iface_cfg['IPADDR'] = subnet['address']
- else:
- raise ValueError("Unknown subnet type '%s' found"
- " for interface '%s'" % (subnet_type,
+ raise ValueError("Unknown subnet type '%s' found"
+ " for interface '%s'" % (subnet_type,
iface_cfg.name))
- if 'netmask' in subnet:
- iface_cfg['NETMASK'] = subnet['netmask']
+
+ # set IPv4 and IPv6 static addresses
+ ipv4_index = -1
+ ipv6_index = -1
+ for i, subnet in enumerate(subnets,start=len(iface_cfg.children)):
+ subnet_type = subnet.get('type')
+ if subnet_type == 'dhcp6':
+ continue
+ elif subnet_type in ['dhcp4', 'dhcp']:
+ continue
+ elif subnet_type == 'static':
+ if subnet_is_ipv6(subnet):
+ ipv6_index = ipv6_index + 1
+ if 'netmask' in subnet and subnet['netmask'] != "":
+ ipv6_cidr = subnet['address'] + '/' + subnet['netmask']
+ else:
+ ipv6_cidr = subnet['address']
+ if ipv6_index == 0:
+ iface_cfg['IPV6ADDR'] = ipv6_cidr
+ elif ipv6_index == 1:
+ iface_cfg['IPV6ADDR_SECONDARIES'] = ipv6_cidr
+ else:
+ iface_cfg['IPV6ADDR_SECONDARIES'] = iface_cfg['IPV6ADDR_SECONDARIES'] + " " + ipv6_cidr
+ else:
+ ipv4_index = ipv4_index + 1
+ if ipv4_index == 0:
+ iface_cfg['IPADDR'] = subnet['address']
+ if 'netmask' in subnet:
+ iface_cfg['NETMASK'] = subnet['netmask']
+ else:
+ iface_cfg['IPADDR' + str(ipv4_index)] = subnet['address']
+ if 'netmask' in subnet:
+ iface_cfg['NETMASK' + str(ipv4_index)] = subnet['netmask']
+
+ @classmethod
+ def _render_subnet_routes(cls, iface_cfg, route_cfg, subnets):
+ for i, subnet in enumerate(subnets,start=len(iface_cfg.children)):
for route in subnet.get('routes', []):
if subnet.get('ipv6'):
gw_cfg = 'IPV6_DEFAULTGW'
@@ -295,15 +338,9 @@ class Renderer(renderer.Renderer):
iface_subnets = iface.get("subnets", [])
iface_cfg = iface_contents[iface_name]
route_cfg = iface_cfg.routes
- if len(iface_subnets) == 1:
- cls._render_subnet(iface_cfg, route_cfg, iface_subnets[0])
- elif len(iface_subnets) > 1:
- for i, isubnet in enumerate(iface_subnets,
- start=len(iface_cfg.children)):
- iface_sub_cfg = iface_cfg.copy()
- iface_sub_cfg.name = "%s:%s" % (iface_name, i)
- iface_cfg.children.append(iface_sub_cfg)
- cls._render_subnet(iface_sub_cfg, route_cfg, isubnet)
+
+ cls._render_subnets(iface_cfg, iface_subnets)
+ cls._render_subnet_routes(iface_cfg, route_cfg, iface_subnets)
@classmethod
def _render_bond_interfaces(cls, network_state, iface_contents):
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index 8837066..b2ef7f5 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -583,9 +583,8 @@ IPV6_AUTOCONF=no
#
BOOTPROTO=static
DEVICE=eth0
-IPV6ADDR=2607:f0d0:1002:0011::2
+IPV6ADDR=2607:f0d0:1002:0011::2/64
IPV6INIT=yes
-NETMASK=64
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 89e7536..3813021 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -203,39 +203,15 @@ nameserver 172.19.0.12
"""
# Created by cloud-init on instance boot automatically, do not edit.
#
-BOOTPROTO=none
-DEVICE=eth0
-HWADDR=fa:16:3e:ed:9a:59
-NM_CONTROLLED=no
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=no
-""".lstrip()),
- ('etc/sysconfig/network-scripts/ifcfg-eth0:0',
- """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
BOOTPROTO=static
DEFROUTE=yes
-DEVICE=eth0:0
+DEVICE=eth0
GATEWAY=172.19.3.254
HWADDR=fa:16:3e:ed:9a:59
IPADDR=172.19.1.34
+IPADDR1=10.0.0.10
NETMASK=255.255.252.0
-NM_CONTROLLED=no
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=no
-""".lstrip()),
- ('etc/sysconfig/network-scripts/ifcfg-eth0:1',
- """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
-BOOTPROTO=static
-DEVICE=eth0:1
-HWADDR=fa:16:3e:ed:9a:59
-IPADDR=10.0.0.10
-NETMASK=255.255.255.0
+NETMASK1=255.255.255.0
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
@@ -264,8 +240,9 @@ nameserver 172.19.0.12
"gateway": "172.19.3.254",
}],
"ip_address": "172.19.1.34", "id": "network0"
- }, {
- "network_id": "public-ipv6",
+ },
+ {
+ "network_id": "public-ipv6-a",
"type": "ipv6", "netmask": "",
"link": "tap1a81968a-79",
"routes": [
@@ -276,7 +253,24 @@ nameserver 172.19.0.12
}
],
"ip_address": "2001:DB8::10", "id": "network1"
- }],
+ },
+ {
+ "network_id": "public-ipv6-b",
+ "type": "ipv6", "netmask": "64",
+ "link": "tap1a81968a-79",
+ "routes": [
+ ],
+ "ip_address": "2001:DB9::10", "id": "network2"
+ },
+ {
+ "network_id": "public-ipv6-c",
+ "type": "ipv6", "netmask": "64",
+ "link": "tap1a81968a-79",
+ "routes": [
+ ],
+ "ip_address": "2001:DB10::10", "id": "network3"
+ }
+ ],
"links": [
{
"ethernet_mac_address": "fa:16:3e:ed:9a:59",
@@ -294,42 +288,17 @@ nameserver 172.19.0.12
"""
# Created by cloud-init on instance boot automatically, do not edit.
#
-BOOTPROTO=none
-DEVICE=eth0
-HWADDR=fa:16:3e:ed:9a:59
-NM_CONTROLLED=no
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=no
-""".lstrip()),
- ('etc/sysconfig/network-scripts/ifcfg-eth0:0',
- """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
BOOTPROTO=static
DEFROUTE=yes
-DEVICE=eth0:0
+DEVICE=eth0
GATEWAY=172.19.3.254
HWADDR=fa:16:3e:ed:9a:59
IPADDR=172.19.1.34
-NETMASK=255.255.252.0
-NM_CONTROLLED=no
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=no
-""".lstrip()),
- ('etc/sysconfig/network-scripts/ifcfg-eth0:1',
- """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
-BOOTPROTO=static
-DEFROUTE=yes
-DEVICE=eth0:1
-HWADDR=fa:16:3e:ed:9a:59
IPV6ADDR=2001:DB8::10
+IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64"
IPV6INIT=yes
IPV6_DEFAULTGW=2001:DB8::1
-NETMASK=
+NETMASK=255.255.252.0
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
References