diff options
author | Scott Moser <smoser@ubuntu.com> | 2016-06-20 22:38:26 -0400 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2016-06-20 22:38:26 -0400 |
commit | b0ea6e5a2c1c26b8faf1dc8303feebb00344e537 (patch) | |
tree | 1ec50e5f8c07ab1c7b4e206a5d0c7dca0858b640 /tests/unittests/test_net.py | |
parent | fe6919dcd37c6c1ecd371e5eb20b605ab20a6420 (diff) | |
parent | 776b0cfe847f531d8d5a235f52673c3da1f06064 (diff) | |
download | vyos-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.py | 277 |
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): |