Merge lp:~mpontillo/maas/fix-parent-mtu-less-than-child--bug-1662948 into lp:~maas-committers/maas/trunk

Proposed by Mike Pontillo
Status: Merged
Approved by: Mike Pontillo
Approved revision: no longer in the source branch.
Merged at revision: 5863
Proposed branch: lp:~mpontillo/maas/fix-parent-mtu-less-than-child--bug-1662948
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 159 lines (+81/-43)
2 files modified
src/maasserver/models/interface.py (+7/-0)
src/maasserver/models/tests/test_interface.py (+74/-43)
To merge this branch: bzr merge lp:~mpontillo/maas/fix-parent-mtu-less-than-child--bug-1662948
Reviewer Review Type Date Requested Status
Lee Trager (community) Approve
Review via email: mp+321125@code.launchpad.net

Commit message

Consider child interface MTUs when deciding a parent interface's effective MTU.

To post a comment you must log in.
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Note: I moved all the MTU-related test cases into their own suite, InterfaceMTUTest, so that future developers working with MTU-related issues have an easy way to run all the interface-model-related tests.

Revision history for this message
Lee Trager (ltrager) wrote :

Should src/maasserver/forms/interface.py be updated to raise a validation error when this occurs, or should the parent MUTS always automatically supersede the child?

review: Needs Information
Revision history for this message
Mike Pontillo (mpontillo) wrote :

I think adding a ValidationError here would just make it hard on the user, since there are so many different ways to determine the effective MTU.

According to the bug reports on this issue (there were a couple duplicates, too), if you try to deploy a node where the parent MTU is less than its children, the deployment will fail and the interfaces will not come online.

Revision history for this message
Lee Trager (ltrager) wrote :

Sounds resonable.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (32.7 KiB)

The attempt to merge lp:~mpontillo/maas/fix-parent-mtu-less-than-child--bug-1662948 into lp:maas failed. Below is the output from the failed tests.

Hit:1 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial InRelease
Get:2 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
Get:3 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
Get:4 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]
Get:5 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates/main Sources [237 kB]
Get:6 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages [499 kB]
Get:7 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates/main Translation-en [200 kB]
Get:8 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates/universe amd64 Packages [448 kB]
Fetched 1,690 kB in 0s (2,249 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 archdetect-deb authbind avahi-utils bash bind9 bind9utils build-essential bzr bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common isc-dhcp-server libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libnss-wrapper libpq-dev make nodejs-legacy npm postgresql psmisc pxelinux python3-all python3-apt python3-attr python3-bson python3-convoy python3-crochet python3-cssselect python3-curtin python3-dev python3-distro-info python3-django python3-django-nose python3-django-piston3 python3-dnspython python3-docutils python3-formencode python3-hivex python3-httplib2 python3-jinja2 python3-jsonschema python3-lxml python3-netaddr python3-netifaces python3-novaclient python3-oauth python3-oauthlib python3-openssl python3-paramiko python3-petname python3-pexpect python3-psycopg2 python3-pyinotify python3-pyparsing python3-pyvmomi python3-requests python3-seamicroclient python3-setuptools python3-simplestreams python3-sphinx python3-tempita python3-twisted python3-txtftp python3-tz python3-yaml python3-zope.interface python-bson python-crochet python-django python-django-piston python-djorm-ext-pgarray python-formencode python-lxml python-netaddr python-netifaces python-pocket-lint python-psycopg2 python-simplejson python-tempita python-twisted python-yaml socat syslinux-common tgt ubuntu-cloudimage-keyring wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
authbind is already the newest version (2.1.1+nmu1).
avahi-utils is already the newest version (0.6.32~rc+dfsg-1ubuntu2).
build-essential is already the newest version (12.1ubuntu2).
debhelper is already the newest version (9.20160115ubuntu3).
distro-info is already the newest version (0.14build1).
git is already the newest version (1:2.7.4-0ubuntu1).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is al...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/models/interface.py'
--- src/maasserver/models/interface.py 2017-03-24 22:52:14 +0000
+++ src/maasserver/models/interface.py 2017-03-28 03:35:50 +0000
@@ -597,6 +597,13 @@
597 # MTU set and it is disconnected.597 # MTU set and it is disconnected.
598 from maasserver.models.vlan import DEFAULT_MTU598 from maasserver.models.vlan import DEFAULT_MTU
599 mtu = DEFAULT_MTU599 mtu = DEFAULT_MTU
600 children = self.get_successors()
601 # Check if any child interface has a greater MTU. It is an invalid
602 # configuration for the parent MTU to be smaller. (LP: #1662948)
603 for child in children:
604 child_mtu = child.get_effective_mtu()
605 if mtu < child_mtu:
606 mtu = child_mtu
600 return mtu607 return mtu
601608
602 def get_links(self):609 def get_links(self):
603610
=== modified file 'src/maasserver/models/tests/test_interface.py'
--- src/maasserver/models/tests/test_interface.py 2017-03-24 22:57:02 +0000
+++ src/maasserver/models/tests/test_interface.py 2017-03-28 03:35:50 +0000
@@ -913,27 +913,6 @@
913 alloc_type=IPADDRESS_TYPE.AUTO, interface=nic1)913 alloc_type=IPADDRESS_TYPE.AUTO, interface=nic1)
914 self.assertTrue(nic1.is_configured())914 self.assertTrue(nic1.is_configured())
915915
916 def test_get_effective_mtu_returns_interface_mtu(self):
917 nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
918 nic_mtu = random.randint(552, 4096)
919 nic1.params = {
920 "mtu": nic_mtu
921 }
922 nic1.save()
923 self.assertEqual(nic_mtu, nic1.get_effective_mtu())
924
925 def test_get_effective_mtu_returns_vlan_mtu(self):
926 nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
927 vlan_mtu = random.randint(552, 4096)
928 nic1.vlan.mtu = vlan_mtu
929 nic1.vlan.save()
930 self.assertEqual(vlan_mtu, nic1.get_effective_mtu())
931
932 def test_get_effective_mtu_returns_default_mtu(self):
933 nic1 = factory.make_Interface(
934 INTERFACE_TYPE.PHYSICAL, disconnected=True)
935 self.assertEqual(DEFAULT_MTU, nic1.get_effective_mtu())
936
937 def test_get_links_returns_links_for_each_type(self):916 def test_get_links_returns_links_for_each_type(self):
938 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)917 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
939 links = []918 links = []
@@ -1372,6 +1351,80 @@
1372 self.assertFalse(reload_object(interface).enabled)1351 self.assertFalse(reload_object(interface).enabled)
13731352
13741353
1354class InterfaceMTUTest(MAASServerTestCase):
1355
1356 def test_get_effective_mtu_returns_default_mtu(self):
1357 nic1 = factory.make_Interface(
1358 INTERFACE_TYPE.PHYSICAL, disconnected=True)
1359 self.assertEqual(DEFAULT_MTU, nic1.get_effective_mtu())
1360
1361 def test_get_effective_mtu_returns_interface_mtu(self):
1362 nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
1363 nic_mtu = random.randint(552, 9100)
1364 nic1.params = {
1365 "mtu": nic_mtu
1366 }
1367 nic1.save()
1368 self.assertEqual(nic_mtu, nic1.get_effective_mtu())
1369
1370 def test_get_effective_mtu_returns_vlan_mtu(self):
1371 nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
1372 vlan_mtu = random.randint(552, 9100)
1373 nic1.vlan.mtu = vlan_mtu
1374 nic1.vlan.save()
1375 self.assertEqual(vlan_mtu, nic1.get_effective_mtu())
1376
1377 def test_get_effective_mtu_considers_jumbo_vlan_children(self):
1378 fabric = factory.make_Fabric()
1379 vlan = factory.make_VLAN(fabric=fabric)
1380 eth0 = factory.make_Interface(
1381 INTERFACE_TYPE.PHYSICAL, vlan=fabric.get_default_vlan())
1382 eth0_vlan = factory.make_Interface(
1383 iftype=INTERFACE_TYPE.VLAN, vlan=vlan, parents=[eth0])
1384 vlan_mtu = random.randint(DEFAULT_MTU + 1, 9100)
1385 eth0_vlan.vlan.mtu = vlan_mtu
1386 eth0_vlan.vlan.save()
1387 self.assertEqual(vlan_mtu, eth0.get_effective_mtu())
1388
1389 def test_get_effective_mtu_returns_highest_vlan_mtu(self):
1390 fabric = factory.make_Fabric()
1391 vlan1 = factory.make_VLAN(fabric=fabric)
1392 vlan2 = factory.make_VLAN(fabric=fabric)
1393 eth0 = factory.make_Interface(
1394 INTERFACE_TYPE.PHYSICAL, vlan=fabric.get_default_vlan())
1395 eth0_vlan1 = factory.make_Interface(
1396 iftype=INTERFACE_TYPE.VLAN, vlan=vlan1, parents=[eth0])
1397 eth0_vlan2 = factory.make_Interface(
1398 iftype=INTERFACE_TYPE.VLAN, vlan=vlan2, parents=[eth0])
1399 eth0_vlan1.vlan.mtu = random.randint(1000, 1999)
1400 eth0_vlan1.vlan.save()
1401 eth0_vlan2.vlan.mtu = random.randint(2000, 2999)
1402 eth0_vlan2.vlan.save()
1403 self.assertEqual(eth0_vlan2.vlan.mtu, eth0.get_effective_mtu())
1404
1405 def test__creates_acquired_bridge_copies_mtu(self):
1406 mtu = random.randint(600, 9100)
1407 parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
1408 parent.params = {'mtu': mtu}
1409 parent.save()
1410 bridge = parent.create_acquired_bridge()
1411 self.assertThat(bridge, MatchesStructure(
1412 name=Equals("br-%s" % parent.get_name()),
1413 mac_address=Equals(parent.mac_address),
1414 node=Equals(parent.node),
1415 vlan=Equals(parent.vlan),
1416 enabled=Equals(True),
1417 acquired=Equals(True),
1418 params=MatchesDict({
1419 "bridge_stp": Equals(False),
1420 "bridge_fd": Equals(15),
1421 "mtu": Equals(mtu),
1422 })
1423 ))
1424 self.assertEquals(
1425 [parent.id], [p.id for p in bridge.parents.all()])
1426
1427
1375class VLANInterfaceTest(MAASServerTestCase):1428class VLANInterfaceTest(MAASServerTestCase):
13761429
1377 def test_vlan_has_generated_name(self):1430 def test_vlan_has_generated_name(self):
@@ -2968,28 +3021,6 @@
2968 self.assertEquals(3021 self.assertEquals(
2969 [parent.id], [p.id for p in bridge.parents.all()])3022 [parent.id], [p.id for p in bridge.parents.all()])
29703023
2971 def test__creates_acquired_bridge_copies_mtu(self):
2972 mtu = random.randint(600, 1000)
2973 parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
2974 parent.params = {'mtu': mtu}
2975 parent.save()
2976 bridge = parent.create_acquired_bridge()
2977 self.assertThat(bridge, MatchesStructure(
2978 name=Equals("br-%s" % parent.get_name()),
2979 mac_address=Equals(parent.mac_address),
2980 node=Equals(parent.node),
2981 vlan=Equals(parent.vlan),
2982 enabled=Equals(True),
2983 acquired=Equals(True),
2984 params=MatchesDict({
2985 "bridge_stp": Equals(False),
2986 "bridge_fd": Equals(15),
2987 "mtu": Equals(mtu),
2988 })
2989 ))
2990 self.assertEquals(
2991 [parent.id], [p.id for p in bridge.parents.all()])
2992
2993 def test__creates_acquired_bridge_moves_links_from_parent_to_bridge(self):3024 def test__creates_acquired_bridge_moves_links_from_parent_to_bridge(self):
2994 parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)3025 parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
2995 auto_ip = factory.make_StaticIPAddress(3026 auto_ip = factory.make_StaticIPAddress(