summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Maerdian <lukas.maerdian@canonical.com>2020-06-18 11:28:28 +0200
committerAndrej Shadura <andrewsh@debian.org>2020-07-25 10:14:32 +0200
commitf029c0a5997898825e2d2883a958c9c7186e62af (patch)
tree3cb9ce140e3fb6cec7ba14dd778f414b36b4cd98
parent8d0813f5c0ee9fb23af0c3ceb6202c9211cc0fb4 (diff)
[PATCH] Fix autopkgtest on arm64 with NM 1.24 (#146)
On arm64 we had a test failure in tests/integration/ethernets.py -> test_manual_addresses, which was caused by the fact that netplan apply was disconnecting ALL available network interfaces via nmcli, in order to reload the new netplan config. This way the IP of the 2nd test DHCP server (dnsmasq on veth43) was lost and did not provide correct responses for the rest of the test. It is not necessary to take all interfaces down, only the ones which are (or were) configured via netplan. This was fixed in the netplan apply command. Note: This should make its way into the Groovy package as a distro-patch, to avoid future autopkgtest failures. Commits: * tests: fix ethernets/test_manual_addresses on arm64 * netplan:apply: disconnect/re-configure only netplan-NM interfaces * tests:ethernets: remove deprecated fix, was fixed via 'netplan apply' * tests: add unit-test for python utils * utils: get rid of default glob in nm_interfaces Gbp-Pq: Name 0004-Fix-autopkgtest-on-arm64-with-NM-1.24-146.patch
-rw-r--r--netplan/cli/commands/apply.py11
-rw-r--r--netplan/cli/utils.py14
-rw-r--r--tests/integration/ethernets.py2
-rw-r--r--tests/test_utils.py49
4 files changed, 74 insertions, 2 deletions
diff --git a/netplan/cli/commands/apply.py b/netplan/cli/commands/apply.py
index 33ff5b5..a38fe88 100644
--- a/netplan/cli/commands/apply.py
+++ b/netplan/cli/commands/apply.py
@@ -74,7 +74,9 @@ class NetplanApply(utils.NetplanCommand):
return
old_files_networkd = bool(glob.glob('/run/systemd/network/*netplan-*'))
- old_files_nm = bool(glob.glob('/run/NetworkManager/system-connections/netplan-*'))
+ old_nm_glob = glob.glob('/run/NetworkManager/system-connections/netplan-*')
+ nm_ifaces = utils.nm_interfaces(old_nm_glob)
+ old_files_nm = bool(old_nm_glob)
generator_call = []
generate_out = None
@@ -101,7 +103,10 @@ class NetplanApply(utils.NetplanCommand):
restart_networkd = bool(glob.glob('/run/systemd/network/*netplan-*'))
if not restart_networkd and old_files_networkd:
restart_networkd = True
- restart_nm = bool(glob.glob('/run/NetworkManager/system-connections/netplan-*'))
+
+ restart_nm_glob = glob.glob('/run/NetworkManager/system-connections/netplan-*')
+ nm_ifaces += utils.nm_interfaces(restart_nm_glob)
+ restart_nm = bool(restart_nm_glob)
if not restart_nm and old_files_nm:
restart_nm = True
@@ -127,6 +132,8 @@ class NetplanApply(utils.NetplanCommand):
if utils.nm_running():
# restarting NM does not cause new config to be applied, need to shut down devices first
for device in devices:
+ if device not in nm_ifaces:
+ continue # do not touch this interface
# ignore failures here -- some/many devices might not be managed by NM
try:
utils.nmcli(['device', 'disconnect', device])
diff --git a/netplan/cli/utils.py b/netplan/cli/utils.py
index 85342fc..4f7e266 100644
--- a/netplan/cli/utils.py
+++ b/netplan/cli/utils.py
@@ -23,6 +23,7 @@ import fnmatch
import argparse
import subprocess
import netifaces
+import re
NM_SERVICE_NAME = 'NetworkManager.service'
NM_SNAP_SERVICE_NAME = 'snap.network-manager.networkmanager.service'
@@ -55,6 +56,19 @@ def nm_running(): # pragma: nocover (covered in autopkgtest)
return False
+def nm_interfaces(paths):
+ pat = re.compile('^interface-name=(.*)$')
+ interfaces = []
+ for path in paths:
+ with open(path, 'r') as f:
+ for line in f:
+ m = pat.match(line)
+ if m:
+ interfaces.append(m.group(1))
+ break # skip to next file
+ return interfaces
+
+
def systemctl_network_manager(action, sync=False): # pragma: nocover (covered in autopkgtest)
service_name = NM_SERVICE_NAME
diff --git a/tests/integration/ethernets.py b/tests/integration/ethernets.py
index 231d337..dc5783b 100644
--- a/tests/integration/ethernets.py
+++ b/tests/integration/ethernets.py
@@ -156,6 +156,8 @@ class _CommonTests():
''' % {'r': self.backend, 'ec': self.dev_e_client, 'e2c': self.dev_e2_client})
self.start_dnsmasq(None, self.dev_e2_ap)
self.generate_and_settle()
+ if self.backend == 'NetworkManager':
+ self.nm_online_full(self.dev_e2_client)
self.assert_iface_up(self.dev_e_client,
['inet 172.16.5.3/20'],
['inet 192.168.5', # old DHCP
diff --git a/tests/test_utils.py b/tests/test_utils.py
new file mode 100644
index 0000000..2c137d4
--- /dev/null
+++ b/tests/test_utils.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2020 Canonical, Ltd.
+# Author: Lukas Märdian <lukas.maerdian@canonical.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 3.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import unittest
+import tempfile
+import glob
+
+import netplan.cli.utils as utils
+
+
+class TestUtils(unittest.TestCase):
+
+ def setUp(self):
+ self.workdir = tempfile.TemporaryDirectory()
+ os.makedirs(os.path.join(self.workdir.name, 'etc/netplan'))
+ os.makedirs(os.path.join(self.workdir.name,
+ 'run/NetworkManager/system-connections'))
+
+ def _create_nm_keyfile(self, filename, ifname):
+ with open(os.path.join(self.workdir.name,
+ 'run/NetworkManager/system-connections/', filename), 'w') as f:
+ f.write('[connection]\n')
+ f.write('key=value\n')
+ f.write('interface-name=%s\n' % ifname)
+ f.write('key2=value2\n')
+
+ def test_nm_interfaces(self):
+ self._create_nm_keyfile('netplan-test.nmconnection', 'eth0')
+ self._create_nm_keyfile('netplan-test2.nmconnection', 'eth1')
+ ifaces = utils.nm_interfaces(glob.glob(os.path.join(self.workdir.name,
+ 'run/NetworkManager/system-connections/*.nmconnection')))
+ self.assertTrue('eth0' in ifaces)
+ self.assertTrue('eth1' in ifaces)
+ self.assertTrue(len(ifaces) == 2)