summaryrefslogtreecommitdiff
path: root/tests/unittests/test_distros/test_netconfig.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unittests/test_distros/test_netconfig.py')
-rw-r--r--tests/unittests/test_distros/test_netconfig.py403
1 files changed, 243 insertions, 160 deletions
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index 6e339355..ccf66161 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -1,20 +1,17 @@
# This file is part of cloud-init. See LICENSE file for license information.
+import copy
import os
-from six import StringIO
+from io import StringIO
from textwrap import dedent
-
-try:
- from unittest import mock
-except ImportError:
- import mock
+from unittest import mock
from cloudinit import distros
from cloudinit.distros.parsers.sys_conf import SysConf
from cloudinit import helpers
from cloudinit import settings
from cloudinit.tests.helpers import (
- FilesystemMockingTestCase, dir2dict, populate_dir)
+ FilesystemMockingTestCase, dir2dict)
from cloudinit import util
@@ -91,9 +88,9 @@ V1_NET_CFG = {'config': [{'name': 'eth0',
'version': 1}
V1_NET_CFG_OUTPUT = """\
-# This file is generated from information provided by
-# the datasource. Changes to it will not persist across an instance.
-# To disable cloud-init's network configuration capabilities, write a file
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
auto lo
@@ -109,13 +106,31 @@ auto eth1
iface eth1 inet dhcp
"""
+V1_NET_CFG_IPV6_OUTPUT = """\
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
+# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
+# network: {config: disabled}
+auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet6 static
+ address 2607:f0d0:1002:0011::2/64
+ gateway 2607:f0d0:1002:0011::1
+
+auto eth1
+iface eth1 inet dhcp
+"""
+
V1_NET_CFG_IPV6 = {'config': [{'name': 'eth0',
'subnets': [{'address':
'2607:f0d0:1002:0011::2',
'gateway':
'2607:f0d0:1002:0011::1',
'netmask': '64',
- 'type': 'static'}],
+ 'type': 'static6'}],
'type': 'physical'},
{'name': 'eth1',
'subnets': [{'control': 'auto',
@@ -125,9 +140,9 @@ V1_NET_CFG_IPV6 = {'config': [{'name': 'eth0',
V1_TO_V2_NET_CFG_OUTPUT = """\
-# This file is generated from information provided by
-# the datasource. Changes to it will not persist across an instance.
-# To disable cloud-init's network configuration capabilities, write a file
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
@@ -141,6 +156,23 @@ network:
dhcp4: true
"""
+V1_TO_V2_NET_CFG_IPV6_OUTPUT = """\
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
+# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
+# network: {config: disabled}
+network:
+ version: 2
+ ethernets:
+ eth0:
+ addresses:
+ - 2607:f0d0:1002:0011::2/64
+ gateway6: 2607:f0d0:1002:0011::1
+ eth1:
+ dhcp4: true
+"""
+
V2_NET_CFG = {
'ethernets': {
'eth7': {
@@ -154,9 +186,9 @@ V2_NET_CFG = {
V2_TO_V2_NET_CFG_OUTPUT = """\
-# This file is generated from information provided by
-# the datasource. Changes to it will not persist across an instance.
-# To disable cloud-init's network configuration capabilities, write a file
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
@@ -213,128 +245,95 @@ class TestNetCfgDistroBase(FilesystemMockingTestCase):
self.assertEqual(v, b2[k])
-class TestNetCfgDistroFreebsd(TestNetCfgDistroBase):
+class TestNetCfgDistroFreeBSD(TestNetCfgDistroBase):
+
+ def setUp(self):
+ super(TestNetCfgDistroFreeBSD, self).setUp()
+ self.distro = self._get_distro('freebsd', renderers=['freebsd'])
- frbsd_ifout = """\
-hn0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
- options=51b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,TSO4,LRO>
- ether 00:15:5d:4c:73:00
- inet6 fe80::215:5dff:fe4c:7300%hn0 prefixlen 64 scopeid 0x2
- inet 10.156.76.127 netmask 0xfffffc00 broadcast 10.156.79.255
- nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
- media: Ethernet autoselect (10Gbase-T <full-duplex>)
- status: active
+ def _apply_and_verify_freebsd(self, apply_fn, config, expected_cfgs=None,
+ bringup=False):
+ if not expected_cfgs:
+ raise ValueError('expected_cfg must not be None')
+
+ tmpd = None
+ with mock.patch('cloudinit.net.freebsd.available') as m_avail:
+ m_avail.return_value = True
+ with self.reRooted(tmpd) as tmpd:
+ util.ensure_dir('/etc')
+ util.ensure_file('/etc/rc.conf')
+ util.ensure_file('/etc/resolv.conf')
+ apply_fn(config, bringup)
+
+ results = dir2dict(tmpd)
+ for cfgpath, expected in expected_cfgs.items():
+ print("----------")
+ print(expected)
+ print("^^^^ expected | rendered VVVVVVV")
+ print(results[cfgpath])
+ print("----------")
+ self.assertEqual(
+ set(expected.split('\n')),
+ set(results[cfgpath].split('\n')))
+ self.assertEqual(0o644, get_mode(cfgpath, tmpd))
+
+ @mock.patch('cloudinit.net.get_interfaces_by_mac')
+ def test_apply_network_config_freebsd_standard(self, ifaces_mac):
+ ifaces_mac.return_value = {
+ '00:15:5d:4c:73:00': 'eth0',
+ }
+ rc_conf_expected = """\
+defaultrouter=192.168.1.254
+ifconfig_eth0='192.168.1.5 netmask 255.255.255.0'
+ifconfig_eth1=DHCP
"""
- @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_list')
- @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_ifname_out')
- def test_get_ip_nic_freebsd(self, ifname_out, iflist):
- frbsd_distro = self._get_distro('freebsd')
- iflist.return_value = "lo0 hn0"
- ifname_out.return_value = self.frbsd_ifout
- res = frbsd_distro.get_ipv4()
- self.assertEqual(res, ['lo0', 'hn0'])
- res = frbsd_distro.get_ipv6()
- self.assertEqual(res, [])
-
- @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_ether')
- @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_ifname_out')
- @mock.patch('cloudinit.distros.freebsd.Distro.get_interface_mac')
- def test_generate_fallback_config_freebsd(self, mac, ifname_out, if_ether):
- frbsd_distro = self._get_distro('freebsd')
-
- if_ether.return_value = 'hn0'
- ifname_out.return_value = self.frbsd_ifout
- mac.return_value = '00:15:5d:4c:73:00'
- res = frbsd_distro.generate_fallback_config()
- self.assertIsNotNone(res)
-
- def test_simple_write_freebsd(self):
- fbsd_distro = self._get_distro('freebsd')
-
- rc_conf = '/etc/rc.conf'
- read_bufs = {
- rc_conf: 'initial-rc-conf-not-validated',
- '/etc/resolv.conf': 'initial-resolv-conf-not-validated',
+ expected_cfgs = {
+ '/etc/rc.conf': rc_conf_expected,
+ '/etc/resolv.conf': ''
}
+ self._apply_and_verify_freebsd(self.distro.apply_network_config,
+ V1_NET_CFG,
+ expected_cfgs=expected_cfgs.copy())
- tmpd = self.tmp_dir()
- populate_dir(tmpd, read_bufs)
- with self.reRooted(tmpd):
- with mock.patch("cloudinit.distros.freebsd.util.subp",
- return_value=('vtnet0', '')):
- fbsd_distro.apply_network(BASE_NET_CFG, False)
- results = dir2dict(tmpd)
-
- self.assertIn(rc_conf, results)
- self.assertCfgEquals(
- dedent('''\
- ifconfig_vtnet0="192.168.1.5 netmask 255.255.255.0"
- ifconfig_vtnet1="DHCP"
- defaultrouter="192.168.1.254"
- '''), results[rc_conf])
- self.assertEqual(0o644, get_mode(rc_conf, tmpd))
-
- def test_simple_write_freebsd_from_v2eni(self):
- fbsd_distro = self._get_distro('freebsd')
-
- rc_conf = '/etc/rc.conf'
- read_bufs = {
- rc_conf: 'initial-rc-conf-not-validated',
- '/etc/resolv.conf': 'initial-resolv-conf-not-validated',
+ @mock.patch('cloudinit.net.get_interfaces_by_mac')
+ def test_apply_network_config_freebsd_ifrename(self, ifaces_mac):
+ ifaces_mac.return_value = {
+ '00:15:5d:4c:73:00': 'vtnet0',
}
+ rc_conf_expected = """\
+ifconfig_vtnet0_name=eth0
+defaultrouter=192.168.1.254
+ifconfig_eth0='192.168.1.5 netmask 255.255.255.0'
+ifconfig_eth1=DHCP
+"""
- tmpd = self.tmp_dir()
- populate_dir(tmpd, read_bufs)
- with self.reRooted(tmpd):
- with mock.patch("cloudinit.distros.freebsd.util.subp",
- return_value=('vtnet0', '')):
- fbsd_distro.apply_network(BASE_NET_CFG_FROM_V2, False)
- results = dir2dict(tmpd)
-
- self.assertIn(rc_conf, results)
- self.assertCfgEquals(
- dedent('''\
- ifconfig_vtnet0="192.168.1.5 netmask 255.255.255.0"
- ifconfig_vtnet1="DHCP"
- defaultrouter="192.168.1.254"
- '''), results[rc_conf])
- self.assertEqual(0o644, get_mode(rc_conf, tmpd))
-
- def test_apply_network_config_fallback_freebsd(self):
- fbsd_distro = self._get_distro('freebsd')
-
- # a weak attempt to verify that we don't have an implementation
- # of _write_network_config or apply_network_config in fbsd now,
- # which would make this test not actually test the fallback.
- self.assertRaises(
- NotImplementedError, fbsd_distro._write_network_config,
- BASE_NET_CFG)
-
- # now run
- mynetcfg = {
- 'config': [{"type": "physical", "name": "eth0",
- "mac_address": "c0:d6:9f:2c:e8:80",
- "subnets": [{"type": "dhcp"}]}],
- 'version': 1}
-
- rc_conf = '/etc/rc.conf'
- read_bufs = {
- rc_conf: 'initial-rc-conf-not-validated',
- '/etc/resolv.conf': 'initial-resolv-conf-not-validated',
+ V1_NET_CFG_RENAME = copy.deepcopy(V1_NET_CFG)
+ V1_NET_CFG_RENAME['config'][0]['mac_address'] = '00:15:5d:4c:73:00'
+
+ expected_cfgs = {
+ '/etc/rc.conf': rc_conf_expected,
+ '/etc/resolv.conf': ''
}
+ self._apply_and_verify_freebsd(self.distro.apply_network_config,
+ V1_NET_CFG_RENAME,
+ expected_cfgs=expected_cfgs.copy())
- tmpd = self.tmp_dir()
- populate_dir(tmpd, read_bufs)
- with self.reRooted(tmpd):
- with mock.patch("cloudinit.distros.freebsd.util.subp",
- return_value=('vtnet0', '')):
- fbsd_distro.apply_network_config(mynetcfg, bring_up=False)
- results = dir2dict(tmpd)
+ @mock.patch('cloudinit.net.get_interfaces_by_mac')
+ def test_apply_network_config_freebsd_nameserver(self, ifaces_mac):
+ ifaces_mac.return_value = {
+ '00:15:5d:4c:73:00': 'eth0',
+ }
- self.assertIn(rc_conf, results)
- self.assertCfgEquals('ifconfig_vtnet0="DHCP"', results[rc_conf])
- self.assertEqual(0o644, get_mode(rc_conf, tmpd))
+ V1_NET_CFG_DNS = copy.deepcopy(V1_NET_CFG)
+ ns = ['1.2.3.4']
+ V1_NET_CFG_DNS['config'][0]['subnets'][0]['dns_nameservers'] = ns
+ expected_cfgs = {
+ '/etc/resolv.conf': 'nameserver 1.2.3.4\n'
+ }
+ self._apply_and_verify_freebsd(self.distro.apply_network_config,
+ V1_NET_CFG_DNS,
+ expected_cfgs=expected_cfgs.copy())
class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase):
@@ -376,6 +375,14 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase):
V1_NET_CFG,
expected_cfgs=expected_cfgs.copy())
+ def test_apply_network_config_ipv6_ub(self):
+ expected_cfgs = {
+ self.eni_path(): V1_NET_CFG_IPV6_OUTPUT
+ }
+ self._apply_and_verify_eni(self.distro.apply_network_config,
+ V1_NET_CFG_IPV6,
+ expected_cfgs=expected_cfgs.copy())
+
class TestNetCfgDistroUbuntuNetplan(TestNetCfgDistroBase):
def setUp(self):
@@ -407,7 +414,7 @@ class TestNetCfgDistroUbuntuNetplan(TestNetCfgDistroBase):
self.assertEqual(0o644, get_mode(cfgpath, tmpd))
def netplan_path(self):
- return '/etc/netplan/50-cloud-init.yaml'
+ return '/etc/netplan/50-cloud-init.yaml'
def test_apply_network_config_v1_to_netplan_ub(self):
expected_cfgs = {
@@ -419,6 +426,16 @@ class TestNetCfgDistroUbuntuNetplan(TestNetCfgDistroBase):
V1_NET_CFG,
expected_cfgs=expected_cfgs.copy())
+ def test_apply_network_config_v1_ipv6_to_netplan_ub(self):
+ expected_cfgs = {
+ self.netplan_path(): V1_TO_V2_NET_CFG_IPV6_OUTPUT,
+ }
+
+ # ub_distro.apply_network_config(V1_NET_CFG_IPV6, False)
+ self._apply_and_verify_netplan(self.distro.apply_network_config,
+ V1_NET_CFG_IPV6,
+ expected_cfgs=expected_cfgs.copy())
+
def test_apply_network_config_v2_passthrough_ub(self):
expected_cfgs = {
self.netplan_path(): V2_TO_V2_NET_CFG_OUTPUT,
@@ -551,24 +568,14 @@ class TestNetCfgDistroOpensuse(TestNetCfgDistroBase):
"""Opensuse uses apply_network_config and renders sysconfig"""
expected_cfgs = {
self.ifcfg_path('eth0'): dedent("""\
- BOOTPROTO=none
- DEFROUTE=yes
- DEVICE=eth0
- GATEWAY=192.168.1.254
+ BOOTPROTO=static
IPADDR=192.168.1.5
NETMASK=255.255.255.0
- NM_CONTROLLED=no
- ONBOOT=yes
- TYPE=Ethernet
- USERCTL=no
+ STARTMODE=auto
"""),
self.ifcfg_path('eth1'): dedent("""\
- BOOTPROTO=dhcp
- DEVICE=eth1
- NM_CONTROLLED=no
- ONBOOT=yes
- TYPE=Ethernet
- USERCTL=no
+ BOOTPROTO=dhcp4
+ STARTMODE=auto
"""),
}
self._apply_and_verify(self.distro.apply_network_config,
@@ -579,24 +586,13 @@ class TestNetCfgDistroOpensuse(TestNetCfgDistroBase):
"""Opensuse uses apply_network_config and renders sysconfig w/ipv6"""
expected_cfgs = {
self.ifcfg_path('eth0'): dedent("""\
- BOOTPROTO=none
- DEFROUTE=yes
- DEVICE=eth0
- IPV6ADDR=2607:f0d0:1002:0011::2/64
- IPV6INIT=yes
- IPV6_DEFAULTGW=2607:f0d0:1002:0011::1
- NM_CONTROLLED=no
- ONBOOT=yes
- TYPE=Ethernet
- USERCTL=no
+ BOOTPROTO=static
+ IPADDR6=2607:f0d0:1002:0011::2/64
+ STARTMODE=auto
"""),
self.ifcfg_path('eth1'): dedent("""\
- BOOTPROTO=dhcp
- DEVICE=eth1
- NM_CONTROLLED=no
- ONBOOT=yes
- TYPE=Ethernet
- USERCTL=no
+ BOOTPROTO=dhcp4
+ STARTMODE=auto
"""),
}
self._apply_and_verify(self.distro.apply_network_config,
@@ -604,6 +600,93 @@ class TestNetCfgDistroOpensuse(TestNetCfgDistroBase):
expected_cfgs=expected_cfgs.copy())
+class TestNetCfgDistroArch(TestNetCfgDistroBase):
+ def setUp(self):
+ super(TestNetCfgDistroArch, self).setUp()
+ self.distro = self._get_distro('arch', renderers=['netplan'])
+
+ def _apply_and_verify(self, apply_fn, config, expected_cfgs=None,
+ bringup=False, with_netplan=False):
+ if not expected_cfgs:
+ raise ValueError('expected_cfg must not be None')
+
+ tmpd = None
+ with mock.patch('cloudinit.net.netplan.available',
+ return_value=with_netplan):
+ with self.reRooted(tmpd) as tmpd:
+ apply_fn(config, bringup)
+
+ results = dir2dict(tmpd)
+ for cfgpath, expected in expected_cfgs.items():
+ print("----------")
+ print(expected)
+ print("^^^^ expected | rendered VVVVVVV")
+ print(results[cfgpath])
+ print("----------")
+ self.assertEqual(expected, results[cfgpath])
+ self.assertEqual(0o644, get_mode(cfgpath, tmpd))
+
+ def netctl_path(self, iface):
+ return '/etc/netctl/%s' % iface
+
+ def netplan_path(self):
+ return '/etc/netplan/50-cloud-init.yaml'
+
+ def test_apply_network_config_v1_without_netplan(self):
+ # Note that this is in fact an invalid netctl config:
+ # "Address=None/None"
+ # But this is what the renderer has been writing out for a long time,
+ # and the test's purpose is to assert that the netctl renderer is
+ # still being used in absence of netplan, not the correctness of the
+ # rendered netctl config.
+ expected_cfgs = {
+ self.netctl_path('eth0'): dedent("""\
+ Address=192.168.1.5/255.255.255.0
+ Connection=ethernet
+ DNS=()
+ Gateway=192.168.1.254
+ IP=static
+ Interface=eth0
+ """),
+ self.netctl_path('eth1'): dedent("""\
+ Address=None/None
+ Connection=ethernet
+ DNS=()
+ Gateway=
+ IP=dhcp
+ Interface=eth1
+ """),
+ }
+
+ # ub_distro.apply_network_config(V1_NET_CFG, False)
+ self._apply_and_verify(self.distro.apply_network_config,
+ V1_NET_CFG,
+ expected_cfgs=expected_cfgs.copy(),
+ with_netplan=False)
+
+ def test_apply_network_config_v1_with_netplan(self):
+ expected_cfgs = {
+ self.netplan_path(): dedent("""\
+ # generated by cloud-init
+ network:
+ version: 2
+ ethernets:
+ eth0:
+ addresses:
+ - 192.168.1.5/24
+ gateway4: 192.168.1.254
+ eth1:
+ dhcp4: true
+ """),
+ }
+
+ with mock.patch('cloudinit.util.is_FreeBSD', return_value=False):
+ self._apply_and_verify(self.distro.apply_network_config,
+ V1_NET_CFG,
+ expected_cfgs=expected_cfgs.copy(),
+ with_netplan=True)
+
+
def get_mode(path, target=None):
return os.stat(util.target_path(target, path)).st_mode & 0o777