diff options
author | Lukas Maerdian <lukas.maerdian@canonical.com> | 2020-06-18 11:28:28 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2020-07-25 10:14:32 +0200 |
commit | f029c0a5997898825e2d2883a958c9c7186e62af (patch) | |
tree | 3cb9ce140e3fb6cec7ba14dd778f414b36b4cd98 | |
parent | 8d0813f5c0ee9fb23af0c3ceb6202c9211cc0fb4 (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.py | 11 | ||||
-rw-r--r-- | netplan/cli/utils.py | 14 | ||||
-rw-r--r-- | tests/integration/ethernets.py | 2 | ||||
-rw-r--r-- | tests/test_utils.py | 49 |
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) |