summaryrefslogtreecommitdiff
path: root/tests/unittests/test_net.py
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2016-06-20 22:38:26 -0400
committerScott Moser <smoser@ubuntu.com>2016-06-20 22:38:26 -0400
commitb0ea6e5a2c1c26b8faf1dc8303feebb00344e537 (patch)
tree1ec50e5f8c07ab1c7b4e206a5d0c7dca0858b640 /tests/unittests/test_net.py
parentfe6919dcd37c6c1ecd371e5eb20b605ab20a6420 (diff)
parent776b0cfe847f531d8d5a235f52673c3da1f06064 (diff)
downloadvyos-cloud-init-b0ea6e5a2c1c26b8faf1dc8303feebb00344e537.tar.gz
vyos-cloud-init-b0ea6e5a2c1c26b8faf1dc8303feebb00344e537.zip
merge with trunk.
test runs to the point where it did, think I got most of the changes incorporated.
Diffstat (limited to 'tests/unittests/test_net.py')
-rw-r--r--tests/unittests/test_net.py277
1 files changed, 252 insertions, 25 deletions
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 34875f7b..a9268d30 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1,7 +1,14 @@
from cloudinit import net
+from cloudinit.net import cmdline
+from cloudinit.net import eni
+from cloudinit.net import network_state
+from cloudinit.net import sysconfig
+from cloudinit.sources.helpers import openstack
from cloudinit import util
+from .helpers import mock
from .helpers import TestCase
+from .helpers import dir2dict
import base64
import copy
@@ -9,9 +16,10 @@ import gzip
import io
import json
import os
+import shutil
+import tempfile
import yaml
-
DHCP_CONTENT_1 = """
DEVICE='eth0'
PROTO='dhcp'
@@ -70,6 +78,71 @@ STATIC_EXPECTED_1 = {
'dns_nameservers': ['10.0.1.1']}],
}
+# Examples (and expected outputs for various renderers).
+OS_SAMPLES = [
+ {
+ 'in_data': {
+ "services": [{"type": "dns", "address": "172.19.0.12"}],
+ "networks": [{
+ "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
+ "type": "ipv4", "netmask": "255.255.252.0",
+ "link": "tap1a81968a-79",
+ "routes": [{
+ "netmask": "0.0.0.0",
+ "network": "0.0.0.0",
+ "gateway": "172.19.3.254",
+ }],
+ "ip_address": "172.19.1.34", "id": "network0"
+ }],
+ "links": [
+ {
+ "ethernet_mac_address": "fa:16:3e:ed:9a:59",
+ "mtu": None, "type": "bridge", "id":
+ "tap1a81968a-79",
+ "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
+ },
+ ],
+ },
+ 'in_macs': {
+ 'fa:16:3e:ed:9a:59': 'eth0',
+ },
+ 'out_sysconfig': [
+ ('etc/sysconfig/network-scripts/ifcfg-eth0',
+ """
+# Created by cloud-init on instance boot automatically, do not edit.
+#
+BOOTPROTO=static
+DEFROUTE=yes
+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/route-eth0',
+ """
+# Created by cloud-init on instance boot automatically, do not edit.
+#
+ADDRESS0=0.0.0.0
+GATEWAY0=172.19.3.254
+NETMASK0=0.0.0.0
+""".lstrip()),
+ ('etc/resolv.conf',
+ """
+; Created by cloud-init on instance boot automatically, do not edit.
+;
+nameserver 172.19.0.12
+""".lstrip()),
+ ('etc/udev/rules.d/70-persistent-net.rules',
+ "".join(['SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
+ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n']))]
+ }
+]
+
EXAMPLE_ENI = """
auto lo
iface lo inet loopback
@@ -228,21 +301,148 @@ config:
"""
-class TestNetConfigParsing(TestCase):
+def _setup_test(tmp_dir, mock_get_devicelist, mock_sys_netdev_info,
+ mock_sys_dev_path):
+ mock_get_devicelist.return_value = ['eth1000']
+ dev_characteristics = {
+ 'eth1000': {
+ "bridge": False,
+ "carrier": False,
+ "dormant": False,
+ "operstate": "down",
+ "address": "07-1C-C6-75-A4-BE",
+ }
+ }
+
+ def netdev_info(name, field):
+ return dev_characteristics[name][field]
+
+ mock_sys_netdev_info.side_effect = netdev_info
+
+ def sys_dev_path(devname, path=""):
+ return tmp_dir + devname + "/" + path
+
+ for dev in dev_characteristics:
+ os.makedirs(os.path.join(tmp_dir, dev))
+ with open(os.path.join(tmp_dir, dev, 'operstate'), 'w') as fh:
+ fh.write("down")
+
+ mock_sys_dev_path.side_effect = sys_dev_path
+
+
+class TestSysConfigRendering(TestCase):
+
+ @mock.patch("cloudinit.net.sys_dev_path")
+ @mock.patch("cloudinit.net.sys_netdev_info")
+ @mock.patch("cloudinit.net.get_devicelist")
+ def test_default_generation(self, mock_get_devicelist,
+ mock_sys_netdev_info,
+ mock_sys_dev_path):
+ tmp_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, tmp_dir)
+ _setup_test(tmp_dir, mock_get_devicelist,
+ mock_sys_netdev_info, mock_sys_dev_path)
+
+ network_cfg = net.generate_fallback_config()
+ ns = network_state.parse_net_config_data(network_cfg,
+ skip_broken=False)
+
+ render_dir = os.path.join(tmp_dir, "render")
+ os.makedirs(render_dir)
+
+ renderer = sysconfig.Renderer()
+ renderer.render_network_state(render_dir, ns)
+
+ render_file = 'etc/sysconfig/network-scripts/ifcfg-eth1000'
+ with open(os.path.join(render_dir, render_file)) as fh:
+ content = fh.read()
+ expected_content = """
+# Created by cloud-init on instance boot automatically, do not edit.
+#
+BOOTPROTO=dhcp
+DEVICE=eth1000
+HWADDR=07-1C-C6-75-A4-BE
+NM_CONTROLLED=no
+ONBOOT=yes
+TYPE=Ethernet
+USERCTL=no
+""".lstrip()
+ self.assertEqual(expected_content, content)
+
+ def test_openstack_rendering_samples(self):
+ tmp_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, tmp_dir)
+ render_dir = os.path.join(tmp_dir, "render")
+ for os_sample in OS_SAMPLES:
+ ex_input = os_sample['in_data']
+ ex_mac_addrs = os_sample['in_macs']
+ network_cfg = openstack.convert_net_json(
+ ex_input, known_macs=ex_mac_addrs)
+ ns = network_state.parse_net_config_data(network_cfg,
+ skip_broken=False)
+ renderer = sysconfig.Renderer()
+ renderer.render_network_state(render_dir, ns)
+ for fn, expected_content in os_sample.get('out_sysconfig', []):
+ with open(os.path.join(render_dir, fn)) as fh:
+ self.assertEqual(expected_content, fh.read())
+
+
+class TestEniNetRendering(TestCase):
+
+ @mock.patch("cloudinit.net.sys_dev_path")
+ @mock.patch("cloudinit.net.sys_netdev_info")
+ @mock.patch("cloudinit.net.get_devicelist")
+ def test_default_generation(self, mock_get_devicelist,
+ mock_sys_netdev_info,
+ mock_sys_dev_path):
+ tmp_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, tmp_dir)
+ _setup_test(tmp_dir, mock_get_devicelist,
+ mock_sys_netdev_info, mock_sys_dev_path)
+
+ network_cfg = net.generate_fallback_config()
+ ns = network_state.parse_net_config_data(network_cfg,
+ skip_broken=False)
+
+ render_dir = os.path.join(tmp_dir, "render")
+ os.makedirs(render_dir)
+
+ renderer = eni.Renderer(
+ {'links_path_prefix': None,
+ 'eni_path': 'interfaces', 'netrules_path': None,
+ })
+ renderer.render_network_state(render_dir, ns)
+
+ self.assertTrue(os.path.exists(os.path.join(render_dir,
+ 'interfaces')))
+ with open(os.path.join(render_dir, 'interfaces')) as fh:
+ contents = fh.read()
+
+ expected = """
+auto lo
+iface lo inet loopback
+
+auto eth1000
+iface eth1000 inet dhcp
+"""
+ self.assertEqual(expected.lstrip(), contents.lstrip())
+
+
+class TestCmdlineConfigParsing(TestCase):
simple_cfg = {
'config': [{"type": "physical", "name": "eth0",
"mac_address": "c0:d6:9f:2c:e8:80",
"subnets": [{"type": "dhcp"}]}]}
- def test_klibc_convert_dhcp(self):
- found = net._klibc_to_config_entry(DHCP_CONTENT_1)
+ def test_cmdline_convert_dhcp(self):
+ found = cmdline._klibc_to_config_entry(DHCP_CONTENT_1)
self.assertEqual(found, ('eth0', DHCP_EXPECTED_1))
- def test_klibc_convert_static(self):
- found = net._klibc_to_config_entry(STATIC_CONTENT_1)
+ def test_cmdline_convert_static(self):
+ found = cmdline._klibc_to_config_entry(STATIC_CONTENT_1)
self.assertEqual(found, ('eth1', STATIC_EXPECTED_1))
- def test_config_from_klibc_net_cfg(self):
+ def test_config_from_cmdline_net_cfg(self):
files = []
pairs = (('net-eth0.cfg', DHCP_CONTENT_1),
('net-eth1.cfg', STATIC_CONTENT_1))
@@ -263,45 +463,72 @@ class TestNetConfigParsing(TestCase):
files.append(fp)
util.write_file(fp, content)
- found = net.config_from_klibc_net_cfg(files=files, mac_addrs=macs)
+ found = cmdline.config_from_klibc_net_cfg(files=files,
+ mac_addrs=macs)
self.assertEqual(found, expected)
def test_cmdline_with_b64(self):
data = base64.b64encode(json.dumps(self.simple_cfg).encode())
encoded_text = data.decode()
- cmdline = 'ro network-config=' + encoded_text + ' root=foo'
- found = net.read_kernel_cmdline_config(cmdline=cmdline)
+ raw_cmdline = 'ro network-config=' + encoded_text + ' root=foo'
+ found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
self.assertEqual(found, self.simple_cfg)
def test_cmdline_with_b64_gz(self):
data = _gzip_data(json.dumps(self.simple_cfg).encode())
encoded_text = base64.b64encode(data).decode()
- cmdline = 'ro network-config=' + encoded_text + ' root=foo'
- found = net.read_kernel_cmdline_config(cmdline=cmdline)
+ raw_cmdline = 'ro network-config=' + encoded_text + ' root=foo'
+ found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
self.assertEqual(found, self.simple_cfg)
class TestEniRoundTrip(TestCase):
+ def setUp(self):
+ super(TestCase, self).setUp()
+ self.tmp_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.tmp_dir)
+
+ def _render_and_read(self, network_config=None, state=None, eni_path=None,
+ links_prefix=None, netrules_path=None):
+ if network_config:
+ ns = network_state.parse_net_config_data(network_config)
+ elif state:
+ ns = state
+ else:
+ raise ValueError("Expected data or state, got neither")
+
+ if eni_path is None:
+ eni_path = 'etc/network/interfaces'
+
+ renderer = eni.Renderer(
+ config={'eni_path': eni_path, 'links_path_prefix': links_prefix,
+ 'netrules_path': netrules_path})
+
+ renderer.render_network_state(self.tmp_dir, ns)
+ return dir2dict(self.tmp_dir)
+
def testsimple_convert_and_render(self):
- network_config = net.convert_eni_data(EXAMPLE_ENI)
- ns = net.parse_net_config_data(network_config)
- eni = net.render_interfaces(ns)
- print("Eni looks like:\n%s" % eni)
- raise Exception("FOO")
+ network_config = eni.convert_eni_data(EXAMPLE_ENI)
+ ns = network_state.parse_net_config_data(network_config)
+ eni_path = 'etc/network/interfaces.d/my.interfaces'
+ eni_full_path = os.path.join(self.tmp_dir, eni_path)
+ renderer = eni.Renderer(config={'eni_path': eni_path})
+ renderer.render_network_state(self.tmp_dir, ns)
+ eni_content = util.load_file(eni_full_path)
+ print("Eni looks like: %s" % eni_content)
+ raise Exception("FOO1")
def testsimple_render_all(self):
- network_config = yaml.load(NETWORK_YAML_ALL)
- ns = net.parse_net_config_data(network_config)
- eni = net.render_interfaces(ns)
- print("Eni looks like:\n%s" % eni)
- raise Exception("FOO")
+ files = self._render_and_read(network_config=yaml.load(NETWORK_YAML_ALL))
+ print("files: %s" % files)
+ raise Exception("FOO2")
- def testsimple_render_small(self):
+ def skiptestsimple_render_small(self):
network_config = yaml.load(NETWORK_YAML_SMALL)
- ns = net.parse_net_config_data(network_config)
+ ns = network_state.parse_net_config_data(network_config)
eni = net.render_interfaces(ns)
print("Eni looks like:\n%s" % eni)
- raise Exception("FOO")
+ raise Exception("FOO3")
def _gzip_data(data):