diff options
author | Scott Moser <smoser@ubuntu.com> | 2016-08-10 09:06:15 -0600 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2016-08-10 09:06:15 -0600 |
commit | c3c3dc693c14175e110b5fe125d4d5f98ace9700 (patch) | |
tree | 8858702c2c8a6ad4bf1bb861a4565e0a9c28e588 /tests/unittests/test_net.py | |
parent | 5bd3493d732e5b1902872958e8681f17cbc81ce5 (diff) | |
download | cloud-init-trunk.tar.gz |
cloud-init development has moved its revision control to git.
It is available at
https://code.launchpad.net/cloud-init
Clone with
git clone https://git.launchpad.net/cloud-init
or
git clone git+ssh://git.launchpad.net/cloud-init
For more information see
https://git.launchpad.net/cloud-init/tree/HACKING.rst
Diffstat (limited to 'tests/unittests/test_net.py')
-rw-r--r-- | tests/unittests/test_net.py | 689 |
1 files changed, 0 insertions, 689 deletions
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py deleted file mode 100644 index 41b9a6d0..00000000 --- a/tests/unittests/test_net.py +++ /dev/null @@ -1,689 +0,0 @@ -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 dir2dict -from .helpers import mock -from .helpers import TestCase - -import base64 -import copy -import gzip -import io -import json -import os -import shutil -import tempfile -import textwrap -import yaml - -DHCP_CONTENT_1 = """ -DEVICE='eth0' -PROTO='dhcp' -IPV4ADDR='192.168.122.89' -IPV4BROADCAST='192.168.122.255' -IPV4NETMASK='255.255.255.0' -IPV4GATEWAY='192.168.122.1' -IPV4DNS0='192.168.122.1' -IPV4DNS1='0.0.0.0' -HOSTNAME='foohost' -DNSDOMAIN='' -NISDOMAIN='' -ROOTSERVER='192.168.122.1' -ROOTPATH='' -filename='' -UPTIME='21' -DHCPLEASETIME='3600' -DOMAINSEARCH='foo.com' -""" - -DHCP_EXPECTED_1 = { - 'name': 'eth0', - 'type': 'physical', - 'subnets': [{'broadcast': '192.168.122.255', - 'control': 'manual', - 'gateway': '192.168.122.1', - 'dns_search': ['foo.com'], - 'type': 'dhcp', - 'netmask': '255.255.255.0', - 'dns_nameservers': ['192.168.122.1']}], -} - - -STATIC_CONTENT_1 = """ -DEVICE='eth1' -PROTO='static' -IPV4ADDR='10.0.0.2' -IPV4BROADCAST='10.0.0.255' -IPV4NETMASK='255.255.255.0' -IPV4GATEWAY='10.0.0.1' -IPV4DNS0='10.0.1.1' -IPV4DNS1='0.0.0.0' -HOSTNAME='foohost' -UPTIME='21' -DHCPLEASETIME='3600' -DOMAINSEARCH='foo.com' -""" - -STATIC_EXPECTED_1 = { - 'name': 'eth1', - 'type': 'physical', - 'subnets': [{'broadcast': '10.0.0.255', 'control': 'manual', - 'gateway': '10.0.0.1', - 'dns_search': ['foo.com'], 'type': 'static', - 'netmask': '255.255.255.0', - '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 - dns-nameservers 10.0.0.1 - dns-search foo.com - -auto eth0 -iface eth0 inet static - address 1.2.3.12 - netmask 255.255.255.248 - broadcast 1.2.3.15 - gateway 1.2.3.9 - dns-nameservers 69.9.160.191 69.9.191.4 -auto eth1 -iface eth1 inet static - address 10.248.2.4 - netmask 255.255.255.248 - broadcast 10.248.2.7 -""" - -RENDERED_ENI = """ -auto lo -iface lo inet loopback - dns-nameservers 10.0.0.1 - dns-search foo.com - -auto eth0 -iface eth0 inet static - address 1.2.3.12 - broadcast 1.2.3.15 - dns-nameservers 69.9.160.191 69.9.191.4 - gateway 1.2.3.9 - netmask 255.255.255.248 - -auto eth1 -iface eth1 inet static - address 10.248.2.4 - broadcast 10.248.2.7 - netmask 255.255.255.248 -""".lstrip() - -NETWORK_CONFIGS = { - 'small': { - 'expected_eni': textwrap.dedent("""\ - auto lo - iface lo inet loopback - dns-nameservers 1.2.3.4 5.6.7.8 - dns-search wark.maas - - iface eth1 inet manual - - auto eth99 - iface eth99 inet dhcp - post-up ifup eth99:1 - - - auto eth99:1 - iface eth99:1 inet static - address 192.168.21.3/24 - dns-nameservers 8.8.8.8 8.8.4.4 - dns-search barley.maas sach.maas - post-up route add default gw 65.61.151.37 || true - pre-down route del default gw 65.61.151.37 || true - """).rstrip(' '), - 'yaml': textwrap.dedent(""" - version: 1 - config: - # Physical interfaces. - - type: physical - name: eth99 - mac_address: "c0:d6:9f:2c:e8:80" - subnets: - - type: dhcp4 - - type: static - address: 192.168.21.3/24 - dns_nameservers: - - 8.8.8.8 - - 8.8.4.4 - dns_search: barley.maas sach.maas - routes: - - gateway: 65.61.151.37 - netmask: 0.0.0.0 - network: 0.0.0.0 - metric: 2 - - type: physical - name: eth1 - mac_address: "cf:d6:af:48:e8:80" - - type: nameserver - address: - - 1.2.3.4 - - 5.6.7.8 - search: - - wark.maas - """), - }, - 'all': { - 'expected_eni': ("""\ -auto lo -iface lo inet loopback - dns-nameservers 8.8.8.8 4.4.4.4 8.8.4.4 - dns-search barley.maas wark.maas foobar.maas - -iface eth0 inet manual - -auto eth1 -iface eth1 inet manual - bond-master bond0 - bond-mode active-backup - -auto eth2 -iface eth2 inet manual - bond-master bond0 - bond-mode active-backup - -iface eth3 inet manual - -iface eth4 inet manual - -# control-manual eth5 -iface eth5 inet dhcp - -auto bond0 -iface bond0 inet6 dhcp - bond-mode active-backup - bond-slaves none - hwaddress aa:bb:cc:dd:ee:ff - -auto br0 -iface br0 inet static - address 192.168.14.2/24 - bridge_ports eth3 eth4 - bridge_stp off - post-up ifup br0:1 - - -auto br0:1 -iface br0:1 inet6 static - address 2001:1::1/64 - -auto bond0.200 -iface bond0.200 inet dhcp - vlan-raw-device bond0 - vlan_id 200 - -auto eth0.101 -iface eth0.101 inet static - address 192.168.0.2/24 - dns-nameservers 192.168.0.10 10.23.23.134 - dns-search barley.maas sacchromyces.maas brettanomyces.maas - gateway 192.168.0.1 - mtu 1500 - vlan-raw-device eth0 - vlan_id 101 - post-up ifup eth0.101:1 - - -auto eth0.101:1 -iface eth0.101:1 inet static - address 192.168.2.10/24 - -post-up route add -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true -pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true -"""), - 'yaml': textwrap.dedent(""" - version: 1 - config: - # Physical interfaces. - - type: physical - name: eth0 - mac_address: "c0:d6:9f:2c:e8:80" - - type: physical - name: eth1 - mac_address: "aa:d6:9f:2c:e8:80" - - type: physical - name: eth2 - mac_address: "c0:bb:9f:2c:e8:80" - - type: physical - name: eth3 - mac_address: "66:bb:9f:2c:e8:80" - - type: physical - name: eth4 - mac_address: "98:bb:9f:2c:e8:80" - # specify how ifupdown should treat iface - # control is one of ['auto', 'hotplug', 'manual'] - # with manual meaning ifup/ifdown should not affect the iface - # useful for things like iscsi root + dhcp - - type: physical - name: eth5 - mac_address: "98:bb:9f:2c:e8:8a" - subnets: - - type: dhcp - control: manual - # VLAN interface. - - type: vlan - name: eth0.101 - vlan_link: eth0 - vlan_id: 101 - mtu: 1500 - subnets: - - type: static - address: 192.168.0.2/24 - gateway: 192.168.0.1 - dns_nameservers: - - 192.168.0.10 - - 10.23.23.134 - dns_search: - - barley.maas - - sacchromyces.maas - - brettanomyces.maas - - type: static - address: 192.168.2.10/24 - # Bond. - - type: bond - name: bond0 - # if 'mac_address' is omitted, the MAC is taken from - # the first slave. - mac_address: "aa:bb:cc:dd:ee:ff" - bond_interfaces: - - eth1 - - eth2 - params: - bond-mode: active-backup - subnets: - - type: dhcp6 - # A Bond VLAN. - - type: vlan - name: bond0.200 - vlan_link: bond0 - vlan_id: 200 - subnets: - - type: dhcp4 - # A bridge. - - type: bridge - name: br0 - bridge_interfaces: - - eth3 - - eth4 - ipv4_conf: - rp_filter: 1 - proxy_arp: 0 - forwarding: 1 - ipv6_conf: - autoconf: 1 - disable_ipv6: 1 - use_tempaddr: 1 - forwarding: 1 - # basically anything in /proc/sys/net/ipv6/conf/.../ - params: - bridge_stp: 'off' - bridge_fd: 0 - bridge_maxwait: 0 - subnets: - - type: static - address: 192.168.14.2/24 - - type: static - address: 2001:1::1/64 # default to /64 - # A global nameserver. - - type: nameserver - address: 8.8.8.8 - search: barley.maas - # global nameservers and search in list form - - type: nameserver - address: - - 4.4.4.4 - - 8.8.4.4 - search: - - wark.maas - - foobar.maas - # A global route. - - type: route - destination: 10.0.0.0/8 - gateway: 11.0.0.1 - metric: 3 - """).lstrip(), - } -} - - -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 TestEniNetworkStateToEni(TestCase): - mycfg = { - 'config': [{"type": "physical", "name": "eth0", - "mac_address": "c0:d6:9f:2c:e8:80", - "subnets": [{"type": "dhcp"}]}], - 'version': 1} - my_mac = 'c0:d6:9f:2c:e8:80' - - def test_no_header(self): - rendered = eni.network_state_to_eni( - network_state=network_state.parse_net_config_data(self.mycfg), - render_hwaddress=True) - self.assertIn(self.my_mac, rendered) - self.assertIn("hwaddress", rendered) - - def test_with_header(self): - header = "# hello world\n" - rendered = eni.network_state_to_eni( - network_state=network_state.parse_net_config_data(self.mycfg), - header=header, render_hwaddress=True) - self.assertIn(header, rendered) - self.assertIn(self.my_mac, rendered) - - def test_no_hwaddress(self): - rendered = eni.network_state_to_eni( - network_state=network_state.parse_net_config_data(self.mycfg), - render_hwaddress=False) - self.assertNotIn(self.my_mac, rendered) - self.assertNotIn("hwaddress", rendered) - - -class TestCmdlineConfigParsing(TestCase): - simple_cfg = { - 'config': [{"type": "physical", "name": "eth0", - "mac_address": "c0:d6:9f:2c:e8:80", - "subnets": [{"type": "dhcp"}]}]} - - def test_cmdline_convert_dhcp(self): - found = cmdline._klibc_to_config_entry(DHCP_CONTENT_1) - self.assertEqual(found, ('eth0', DHCP_EXPECTED_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_cmdline_net_cfg(self): - files = [] - pairs = (('net-eth0.cfg', DHCP_CONTENT_1), - ('net-eth1.cfg', STATIC_CONTENT_1)) - - macs = {'eth1': 'b8:ae:ed:75:ff:2b', - 'eth0': 'b8:ae:ed:75:ff:2a'} - - dhcp = copy.deepcopy(DHCP_EXPECTED_1) - dhcp['mac_address'] = macs['eth0'] - - static = copy.deepcopy(STATIC_EXPECTED_1) - static['mac_address'] = macs['eth1'] - - expected = {'version': 1, 'config': [dhcp, static]} - with util.tempdir() as tmpd: - for fname, content in pairs: - fp = os.path.join(tmpd, fname) - files.append(fp) - util.write_file(fp, content) - - 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() - 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() - 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 = eni.convert_eni_data(EXAMPLE_ENI) - files = self._render_and_read(network_config=network_config) - self.assertEqual( - RENDERED_ENI.splitlines(), - files['/etc/network/interfaces'].splitlines()) - - def testsimple_render_all(self): - entry = NETWORK_CONFIGS['all'] - files = self._render_and_read(network_config=yaml.load(entry['yaml'])) - self.assertEqual( - entry['expected_eni'].splitlines(), - files['/etc/network/interfaces'].splitlines()) - - def testsimple_render_small(self): - entry = NETWORK_CONFIGS['small'] - files = self._render_and_read(network_config=yaml.load(entry['yaml'])) - self.assertEqual( - entry['expected_eni'].splitlines(), - files['/etc/network/interfaces'].splitlines()) - - -def _gzip_data(data): - with io.BytesIO() as iobuf: - gzfp = gzip.GzipFile(mode="wb", fileobj=iobuf) - gzfp.write(data) - gzfp.close() - return iobuf.getvalue() |