~curtin-dev/curtin/trunk

« back to all changes in this revision

Viewing changes to tests/vmtests/test_network_mtu.py

  • Committer: Ryan Harper
  • Date: 2016-08-29 21:06:46 UTC
  • mfrom: (416.4.28 trunk.more-ipv6)
  • Revision ID: ryan.harper@canonical.com-20160829210646-1f9pv8r691iggedz
curtin/net: overhaul of eni rendering to handle mixed ipv4/ipv6 configs

To ensure complete ipv4/ipv6 support for advanced and stacked
configurations update how curtin.net renders /etc/network/interfaces for
different releases (precise -> yakkety). ifupdown has subtle issues with
various networking features and curtin needs to ensure consistent
behavior.

- Propery handle emitting the 'auto' control tag for stacked interfaces,
  like vlans over bonds
- Workaround LP:1609367 by rendering ifupdown hooks to handle the various
  cases. This works generically in all ubuntu releases 
- Add vmtests for mtu settings
- Drop the use of ipv4 alias interfaces (eth0:1, eth0:2) and instead just
  add additional e/n/i stanzas. ifupdown already uses iproute2's /sbin/ip
  which supports adding additional ip addresses to an interface without the
  use of the v4-only interface alias structure. This provides consistent
  behavior for all types of interfaces (physical, vlan, bonds, and stacked
  interfaces) across all releases. Two side-effects: 1) users can no longer
  `ifdown eth0:1` to remove a single ip address from an interface; if down
  eth0 will take _all_ ip addresses on that interface. 2) ifconfig output
  only shows *one* ipv4 address, so users will need to use /sbin/ip addr
  show <interface> to see all ip addresses assigned to an interface.
- Add vmtests for alias settings
- Restructure all of the common network testcases into a single class
  TestNetworkTestBaseAbs, all varients testing network inherit from this
  class and override only the config file and any special case test-cases
  and file collection
- Global replace of testcase use of 'with open' and instead use
  load_collect_file()
  - Fix falsepositive uefi and multipath test this replacement exposed.
- Add ip_a_to_dict parser for `/sbin/ip a` output
  - drop ifconfig_a parser

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from .releases import base_vm_classes as relbase
 
2
from .test_network_ipv6 import TestNetworkIPV6Abs
 
3
from curtin import util
 
4
 
 
5
import os
 
6
import textwrap
 
7
 
 
8
 
 
9
class TestNetworkMtuAbs(TestNetworkIPV6Abs):
 
10
    """ Test that the mtu of the ipv6 address is properly
 
11
 
 
12
    1.  devices default MTU to 1500, test if mtu under
 
13
        inet6 stanza can be set separately from device
 
14
        mtu (works on Xenial and newer ifupdown), check
 
15
        via sysctl.
 
16
 
 
17
    2.  if ipv6 mtu is > than underlying device, this fails
 
18
        and is unnoticed, ifupdown/hook should fix by changing
 
19
        mtu of underlying device to the same size as the ipv6
 
20
        mtu
 
21
 
 
22
    3.  order of the v4 vs. v6 stanzas could affect final mtu
 
23
        ipv6 first, then ipv4 with mtu.
 
24
    """
 
25
    conf_file = "examples/tests/network_mtu.yaml"
 
26
    collect_scripts = TestNetworkIPV6Abs.collect_scripts + [textwrap.dedent("""
 
27
        cd OUTPUT_COLLECT_D
 
28
        proc_v6="/proc/sys/net/ipv6/conf"
 
29
        for f in `seq 0 7`; do
 
30
            cat /sys/class/net/interface${f}/mtu > interface${f}_dev_mtu;
 
31
            cat $proc_v6/interface${f}/mtu > interface${f}_ipv6_mtu;
 
32
        done
 
33
        if [ -e /var/log/upstart ]; then
 
34
          cp -a /var/log/upstart ./var_log_upstart
 
35
        fi
 
36
        """)]
 
37
 
 
38
    def _load_mtu_data(self, ifname):
 
39
        """ load mtu related files by interface name.
 
40
            returns a dictionary with the follwing
 
41
            keys:  'device', and 'ipv6'.  """
 
42
 
 
43
        mtu_fn = {
 
44
            'device': "%s_dev_mtu" % ifname,
 
45
            'ipv6': "%s_ipv6_mtu" % ifname,
 
46
        }
 
47
        mtu_val = {}
 
48
        for fnk in mtu_fn.keys():
 
49
            fn = os.path.join(self.td.collect, mtu_fn[fnk])
 
50
            mtu_val.update({fnk: int(util.load_file(fn))})
 
51
 
 
52
        return mtu_val
 
53
 
 
54
    def _check_subnet_mtu(self, subnet, iface):
 
55
        mtu_data = self._load_mtu_data(iface['name'])
 
56
        print('subnet:%s' % subnet)
 
57
        print('mtu_data:%s' % mtu_data)
 
58
        # ipv4 address mtu changes *device* mtu
 
59
        if '.' in subnet['address']:
 
60
            print('subnet_mtu=%s device_mtu=%s' % (int(subnet['mtu']),
 
61
                                                   int(mtu_data['device'])))
 
62
            self.assertEqual(int(subnet['mtu']),
 
63
                             int(mtu_data['device']))
 
64
        # ipv6 address mtu changes *protocol* mtu
 
65
        elif ':' in subnet['address']:
 
66
            print('subnet_mtu=%s ipv6_mtu=%s' % (int(subnet['mtu']),
 
67
                                                 int(mtu_data['device'])))
 
68
            self.assertEqual(int(subnet['mtu']),
 
69
                             int(mtu_data['ipv6']))
 
70
 
 
71
    def _check_iface_subnets(self, ifname):
 
72
        network_state = self.get_network_state()
 
73
        interfaces = network_state.get('interfaces')
 
74
 
 
75
        iface = interfaces.get(ifname)
 
76
        subnets = iface.get('subnets')
 
77
        print('iface=%s subnets=%s' % (iface['name'], subnets))
 
78
        for subnet in subnets:
 
79
            if 'mtu' in subnet:
 
80
                self._check_subnet_mtu(subnet, iface)
 
81
 
 
82
    def _disabled_ipv4_and_ipv6_mtu_all(self):
 
83
        """ we don't pass all tests, skip for now """
 
84
        network_state = self.get_network_state()
 
85
        interfaces = network_state.get('interfaces')
 
86
 
 
87
        for iface in interfaces.values():
 
88
            subnets = iface.get('subnets', {})
 
89
            if subnets:
 
90
                for index, subnet in zip(range(0, len(subnets)), subnets):
 
91
                    print("iface=%s subnet=%s" % (iface['name'], subnet))
 
92
                    if 'mtu' in subnet:
 
93
                        self._check_subnet_mtu(subnet, iface)
 
94
 
 
95
    def test_ipv6_mtu_smaller_than_ipv4_non_default(self):
 
96
        self._check_iface_subnets('interface0')
 
97
 
 
98
    def test_ipv6_mtu_equal_ipv4_non_default(self):
 
99
        self._check_iface_subnets('interface1')
 
100
 
 
101
    def test_ipv6_mtu_higher_than_default_no_ipv4_mtu(self):
 
102
        self._check_iface_subnets('interface2')
 
103
 
 
104
    def test_ipv6_mtu_higher_than_default_no_ipv4_iface_up(self):
 
105
        self._check_iface_subnets('interface3')
 
106
 
 
107
    def test_ipv6_mtu_smaller_than_ipv4_v6_iface_first(self):
 
108
        self._check_iface_subnets('interface4')
 
109
 
 
110
    def test_ipv6_mtu_equal_ipv4_non_default_v6_iface_first(self):
 
111
        self._check_iface_subnets('interface5')
 
112
 
 
113
    def test_ipv6_mtu_higher_than_default_no_ipv4_mtu_v6_iface_first(self):
 
114
        self._check_iface_subnets('interface6')
 
115
 
 
116
    def test_ipv6_mtu_higher_than_default_no_ipv4_iface_v6_iface_first(self):
 
117
        self._check_iface_subnets('interface7')
 
118
 
 
119
 
 
120
class PreciseHWETTestNetworkMtu(relbase.precise_hwe_t, TestNetworkMtuAbs):
 
121
    # FIXME: Precise mtu / ipv6 is buggy
 
122
    __test__ = False
 
123
 
 
124
 
 
125
class TrustyTestNetworkMtu(relbase.trusty, TestNetworkMtuAbs):
 
126
    __test__ = True
 
127
 
 
128
    # FIXME: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809714
 
129
    # fixed in newer ifupdown than is in trusty
 
130
    def test_ipv6_mtu_smaller_than_ipv4_non_default(self):
 
131
        # trusty ifupdown uses device mtu to change v6 mtu
 
132
        pass
 
133
 
 
134
 
 
135
class TrustyHWEUTestNetworkMtu(relbase.trusty_hwe_u, TrustyTestNetworkMtu):
 
136
    # unsupported kernel, 2016-08
 
137
    __test__ = False
 
138
 
 
139
 
 
140
class TrustyHWEVTestNetworkMtu(relbase.trusty_hwe_v, TrustyTestNetworkMtu):
 
141
    # unsupported kernel, 2016-08
 
142
    __test__ = False
 
143
 
 
144
 
 
145
class TrustyHWEWTestNetworkMtu(relbase.trusty_hwe_w, TrustyTestNetworkMtu):
 
146
    # unsupported kernel, 2016-08
 
147
    __test__ = False
 
148
 
 
149
 
 
150
class XenialTestNetworkMtu(relbase.xenial, TestNetworkMtuAbs):
 
151
    __test__ = True
 
152
 
 
153
 
 
154
class YakketyTestNetworkMtu(relbase.yakkety, TestNetworkMtuAbs):
 
155
    __test__ = True