diff -Nru systemd-228/debian/changelog systemd-228/debian/changelog --- systemd-228/debian/changelog 2015-11-19 11:41:31.000000000 +0000 +++ systemd-228/debian/changelog 2015-11-23 10:35:34.000000000 +0000 @@ -1,27 +1,4 @@ -systemd (228-1ubuntu2) xenial; urgency=medium - - * Merge with Debian to fix FTBFS. - - -- Martin Pitt Thu, 19 Nov 2015 12:41:25 +0100 - -systemd (228-3) UNRELEASED; urgency=medium - - * debian/rules: Remove temporary debug output from test failures again. All - Debian buildd kernels are recent enough now, but add a check for kernels - older than 3.13 and ignore test failures for those. - - -- Martin Pitt Thu, 19 Nov 2015 12:09:17 +0100 - -systemd (228-2) unstable; urgency=medium - - * Remove wrong endianess conversion in test-siphash24 to fix FTBFS on - big-endian machines. - * Bump libseccomp-dev build dependency to indicate required versions for - backporting to jessie. (Closes: #805497) - - -- Martin Pitt Thu, 19 Nov 2015 11:37:45 +0100 - -systemd (228-1ubuntu1) xenial; urgency=medium +systemd (228-2ubuntu1) xenial; urgency=medium * Merge with Debian unstable. Remaining Ubuntu changes: - Hack to support system-image read-only /etc, and modify files in @@ -71,7 +48,41 @@ that changes to point to systemd during the upgrade. This avoids running systemd during a dist-upgrade. (LP: #1430479) - -- Martin Pitt Wed, 18 Nov 2015 18:11:38 +0100 + -- Martin Pitt Mon, 23 Nov 2015 11:35:02 +0100 + +systemd (228-3) UNRELEASED; urgency=medium + + [ Martin Pitt ] + * debian/rules: Remove temporary debug output from test failures again. All + Debian buildd kernels are recent enough now, but add a check for kernels + older than 3.13 and ignore test failures for those. + * debian/tests/networkd: Factor out dnsmasq specific test "router" setup, so + that we can test against other implementations. + * debian/tests/networkd: Add router setup using an (isolated) networkd + process for configuring the veths and DHCP server. + * debian/tests/networkd: On failure, only show journal for current test. + * systemd-networkd-resolvconf-update.service: Wait for getting a name + server, not just for getting online. + * debian/tests/boot-and-services: Wait until bash crash stack trace is in + the journal before asserting on it. Also relax RE to work on non-x86 + architectures. + * debian/tests/networkd: If /etc/resolv.conf already has three nameservers, + accept that too (as then the additional test one can't be added any more). + + [ Michael Biebl ] + * Bump Build-Depends on libdw-dev to (>= 0.158) as per configure.ac. + (Closes: #805631) + + -- Martin Pitt Thu, 19 Nov 2015 12:09:17 +0100 + +systemd (228-2) unstable; urgency=medium + + * Remove wrong endianess conversion in test-siphash24 to fix FTBFS on + big-endian machines. + * Bump libseccomp-dev build dependency to indicate required versions for + backporting to jessie. (Closes: #805497) + + -- Martin Pitt Thu, 19 Nov 2015 11:37:45 +0100 systemd (228-1) unstable; urgency=medium diff -Nru systemd-228/debian/control systemd-228/debian/control --- systemd-228/debian/control 2015-11-19 11:41:31.000000000 +0000 +++ systemd-228/debian/control 2015-11-23 10:35:34.000000000 +0000 @@ -42,8 +42,9 @@ libkmod-dev (>= 15), libblkid-dev (>= 2.24), libmount-dev (>= 2.27.1), - libseccomp-dev (>= 2.2.1-2~) [amd64 arm64 armel armhf i386 mips mipsel mips64 mips64el x32 powerpc ppc64el], - libdw-dev , + libseccomp-dev (>= 1.0.0) [amd64 arm64 armel armhf i386 mips mipsel mips64 mips64el x32 powerpc ppc64el], + libdw-dev (>= 0.158) , + linux-base , python3:native, python3-lxml:native diff -Nru systemd-228/debian/extra/units/systemd-networkd-resolvconf-update.service systemd-228/debian/extra/units/systemd-networkd-resolvconf-update.service --- systemd-228/debian/extra/units/systemd-networkd-resolvconf-update.service 2015-11-19 11:41:31.000000000 +0000 +++ systemd-228/debian/extra/units/systemd-networkd-resolvconf-update.service 2015-11-23 10:35:34.000000000 +0000 @@ -7,6 +7,6 @@ [Service] Type=oneshot StartLimitBurst=20 -# we need to wait for "online" here, as we might be triggered several times in short succession during restarting networkd -ExecStart=/bin/sh -c 'if /lib/systemd/systemd-networkd-wait-online --timeout=30; then sed -n "/^DNS=/ { s/^DNS=/nameserver /; p}" /run/systemd/netif/state | /sbin/resolvconf -a networkd; fi' +# we might be triggered several times in short succession during restarting networkd, so wait until we get a DNS entry +ExecStart=/bin/sh -c 'for timeout in `seq 30`; do out=$(sed -n "/^DNS=/ { s/^DNS=/nameserver /; p}" /run/systemd/netif/state); [ -z "$out" ] || break; sleep 1; done; echo "$out" | /sbin/resolvconf -a networkd' diff -Nru systemd-228/debian/rules systemd-228/debian/rules --- systemd-228/debian/rules 2015-11-19 11:41:31.000000000 +0000 +++ systemd-228/debian/rules 2015-11-23 10:35:34.000000000 +0000 @@ -270,7 +270,7 @@ env -u LD_PRELOAD make -C build-deb check || ( \ cd build-deb; \ for f in test-*.log; do echo "==== $$f ===="; cat $$f; done; \ - if dpkg --compare-versions $$(uname -r) gt 3.13; then \ + if linux-version compare "$$(uname -r)" ge 3.13; then \ exit 1; \ else \ echo "Ignoring test failure under too old kernel $$(uname -r)"; \ diff -Nru systemd-228/debian/tests/boot-and-services systemd-228/debian/tests/boot-and-services --- systemd-228/debian/tests/boot-and-services 2015-11-19 11:41:31.000000000 +0000 +++ systemd-228/debian/tests/boot-and-services 2015-11-23 10:35:34.000000000 +0000 @@ -437,13 +437,14 @@ timeout = 50 while timeout > 0: journal = subprocess.check_output(['journalctl', '/lib/systemd/systemd-coredump']) - if re.search(b'Process.*bash.*dumped core', journal): + if re.search(b'Process.*bash.*dumped core', journal) and \ + re.search(b'#[0-9] .*bash', journal): break time.sleep(0.1) timeout -= 1 self.assertRegex(journal, b'Process.*bash.*dumped core') self.assertIn(b'Stack trace', journal) - self.assertRegex(journal, b'#[0-9] .* main.*bash') + self.assertRegex(journal, b'#[0-9] .*bash') def pre_boot_setup(): diff -Nru systemd-228/debian/tests/networkd systemd-228/debian/tests/networkd --- systemd-228/debian/tests/networkd 2015-11-19 11:41:31.000000000 +0000 +++ systemd-228/debian/tests/networkd 2015-11-23 10:35:34.000000000 +0000 @@ -31,18 +31,19 @@ import unittest import tempfile import subprocess +import shutil networkd_active = subprocess.call(['systemctl', 'is-active', '--quiet', 'systemd-networkd']) == 0 +have_dnsmasq = shutil.which('dnsmasq') + @unittest.skipIf(networkd_active, 'networkd is already active') -class TestNetworkd(unittest.TestCase): - @classmethod +class ClientTestBase: def setUp(self): self.iface = 'test_eth42' self.if_router = 'router_eth42' - self.dnsmasq = None self.workdir_obj = tempfile.TemporaryDirectory() self.workdir = self.workdir_obj.name self.config = '/run/systemd/network/test_eth42.network' @@ -60,50 +61,41 @@ else: self.fail('systemd-networkd-wait-online not found') + # get current journal cursor + out = subprocess.check_output(['journalctl', '-b', '--quiet', + '--no-pager', '-n0', '--show-cursor'], + universal_newlines=True) + self.assertTrue(out.startswith('-- cursor:')) + self.journal_cursor = out.split()[-1] + def tearDown(self): self.shutdown_iface() if os.path.exists(self.config): os.unlink(self.config) subprocess.call(['systemctl', 'stop', 'systemd-networkd']) + def show_journal(self, unit): + '''Show journal of given unit since start of the test''' + + print('---- %s ----' % unit) + sys.stdout.flush() + subprocess.call(['journalctl', '-b', '--no-pager', '--quiet', + '--cursor', self.journal_cursor, '-u', unit]) + def create_iface(self, ipv6=False): '''Create test interface with DHCP server behind it''' - # add veth pair - subprocess.check_call(['ip', 'link', 'add', 'name', self.iface, 'type', - 'veth', 'peer', 'name', self.if_router]) - - # give our router an IP - subprocess.check_call(['ip', 'a', 'flush', 'dev', self.if_router]) - subprocess.check_call(['ip', 'a', 'add', '192.168.5.1/24', 'dev', self.if_router]) - if ipv6: - subprocess.check_call(['ip', 'a', 'add', '2600::1/64', 'dev', self.if_router]) - subprocess.check_call(['ip', 'link', 'set', self.if_router, 'up']) - - # add DHCP server - self.dnsmasq_log = os.path.join(self.workdir, 'dnsmasq.log') - lease_file = os.path.join(self.workdir, 'dnsmasq.leases') - if ipv6: - extra_opts = ['--enable-ra', '--dhcp-range=2600::10,2600::20'] - else: - extra_opts = [] - self.dnsmasq = subprocess.Popen( - ['dnsmasq', '--keep-in-foreground', '--log-queries', - '--log-facility=' + self.dnsmasq_log, '--conf-file=/dev/null', - '--dhcp-leasefile=' + lease_file, '--bind-interfaces', - '--interface=' + self.if_router, '--except-interface=lo', - '--dhcp-range=192.168.5.10,192.168.5.200'] + extra_opts) + raise NotImplementedError('must be implemented by a subclass') def shutdown_iface(self): '''Remove test interface and stop DHCP server''' - if self.if_router: - subprocess.check_call(['ip', 'link', 'del', 'dev', self.if_router]) - self.if_router = None - if self.dnsmasq: - self.dnsmasq.kill() - self.dnsmasq.wait() - self.dnsmasq = None + raise NotImplementedError('must be implemented by a subclass') + + def print_server_log(self): + '''Print DHCP server log for debugging failures''' + + raise NotImplementedError('must be implemented by a subclass') def do_test(self, coldplug=True, ipv6=False, extra_opts='', online_timeout=10, dhcp_mode='yes'): @@ -132,11 +124,13 @@ # longer, as the iface is "configured" already with IPv4 timeout = 10 while timeout > 0: - out = subprocess.check_output(['ip', '-6', 'a', 'show', 'dev', self.iface]) - if b'state UP' in out and b'scope global' in out: + out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.iface]) + if b'state UP' in out and b'inet6 2600' in out: break time.sleep(1) timeout -= 1 + else: + self.fail('timed out waiting for IPv6 configuration') self.assertRegex(out, b'inet6 2600::.* scope global .*dynamic') self.assertRegex(out, b'inet6 fe80::.* scope link') @@ -168,26 +162,33 @@ self.assertRegex(out, b'Gateway:\s+192.168.5.1') self.assertRegex(out, b'DNS:\s+192.168.5.1') except (AssertionError, subprocess.CalledProcessError): - # show networkd status, journal, and dnsmasq log on failure + # show networkd status, journal, and DHCP server log on failure with open(self.config) as f: print('\n---- %s ----\n%s' % (self.config, f.read())) + print('---- interface status ----') + sys.stdout.flush() + subprocess.call(['ip', 'a', 'show', 'dev', self.iface]) print('---- networkctl status %s ----' % self.iface) + sys.stdout.flush() subprocess.call(['networkctl', 'status', self.iface]) - print('---- networkd journal ----') - subprocess.call(['journalctl', '-b', '--no-pager', '-u', 'systemd-networkd.service']) - with open(self.dnsmasq_log) as f: - sys.stdout.write('\n\n---- dnsmasq log ----\n%s\n------\n\n' % f.read()) + self.show_journal('systemd-networkd.service') + self.print_server_log() raise # verify resolv.conf if it gets dynamically managed if os.path.islink('/etc/resolv.conf'): for timeout in range(50): with open('/etc/resolv.conf') as f: - if 'nameserver 192.168.5.1\n' in f.read(): - break + contents = f.read() + if 'nameserver 192.168.5.1\n' in contents: + break + # resolv.conf can have at most three nameservers; if we already + # have three different ones, that's also okay + if contents.count('nameserver ') >= 3: + break time.sleep(0.1) else: - subprocess.call(['journalctl', '-b', '-u', 'systemd-networkd-resolvconf-update.service']) + self.show_journal('systemd-networkd-resolvconf-update.service') self.fail('nameserver 192.168.5.1 not found in /etc/resolv.conf') if not coldplug: @@ -224,6 +225,151 @@ self.do_test(coldplug=False, ipv6=True) +@unittest.skipUnless(have_dnsmasq, 'dnsmasq not installed') +class DnsmasqClientTest(ClientTestBase, unittest.TestCase): + '''Test networkd client against dnsmasq''' + + def setUp(self): + super().setUp() + self.dnsmasq = None + + def create_iface(self, ipv6=False): + '''Create test interface with DHCP server behind it''' + + # add veth pair + subprocess.check_call(['ip', 'link', 'add', 'name', self.iface, 'type', + 'veth', 'peer', 'name', self.if_router]) + + # give our router an IP + subprocess.check_call(['ip', 'a', 'flush', 'dev', self.if_router]) + subprocess.check_call(['ip', 'a', 'add', '192.168.5.1/24', 'dev', self.if_router]) + if ipv6: + subprocess.check_call(['ip', 'a', 'add', '2600::1/64', 'dev', self.if_router]) + subprocess.check_call(['ip', 'link', 'set', self.if_router, 'up']) + + # add DHCP server + self.dnsmasq_log = os.path.join(self.workdir, 'dnsmasq.log') + lease_file = os.path.join(self.workdir, 'dnsmasq.leases') + if ipv6: + extra_opts = ['--enable-ra', '--dhcp-range=2600::10,2600::20'] + else: + extra_opts = [] + self.dnsmasq = subprocess.Popen( + ['dnsmasq', '--keep-in-foreground', '--log-queries', + '--log-facility=' + self.dnsmasq_log, '--conf-file=/dev/null', + '--dhcp-leasefile=' + lease_file, '--bind-interfaces', + '--interface=' + self.if_router, '--except-interface=lo', + '--dhcp-range=192.168.5.10,192.168.5.200'] + extra_opts) + + def shutdown_iface(self): + '''Remove test interface and stop DHCP server''' + + if self.if_router: + subprocess.check_call(['ip', 'link', 'del', 'dev', self.if_router]) + self.if_router = None + if self.dnsmasq: + self.dnsmasq.kill() + self.dnsmasq.wait() + self.dnsmasq = None + + def print_server_log(self): + '''Print DHCP server log for debugging failures''' + + with open(self.dnsmasq_log) as f: + sys.stdout.write('\n\n---- dnsmasq log ----\n%s\n------\n\n' % f.read()) + + +class NetworkdClientTest(ClientTestBase, unittest.TestCase): + '''Test networkd client against networkd server''' + + def setUp(self): + super().setUp() + self.dnsmasq = None + + def create_iface(self, ipv6=False): + '''Create test interface with DHCP server behind it''' + + # run "router-side" networkd in own mount namespace to shield it from + # "client-side" configuration and networkd + (fd, script) = tempfile.mkstemp(prefix='networkd-router.sh') + self.addCleanup(os.remove, script) + with os.fdopen(fd, 'w+') as f: + f.write('''#!/bin/sh -eu +mkdir -p /run/systemd/network +mkdir -p /run/systemd/netif +mount -t tmpfs none /run/systemd/network +mount -t tmpfs none /run/systemd/netif +mount -t tmpfs none /run/dbus +# create router/client veth pair +cat << EOF > /run/systemd/network/test.netdev +[NetDev] +Name=%(ifr)s +Kind=veth + +[Peer] +Name=%(ifc)s +EOF + +cat << EOF > /run/systemd/network/test.network +[Match] +Name=%(ifr)s + +[Network] +Address=192.168.5.1/24 +%(addr6)s +DHCPServer=yes + +[DHCPServer] +PoolOffset=10 +PoolSize=50 +DNS=192.168.5.1 +EOF + +# run networkd as in systemd-networkd.service +exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=//; p}') +''' % {'ifr': self.if_router, 'ifc': self.iface, 'addr6': ipv6 and 'Address=2600::1/64' or ''}) + + os.fchmod(fd, 0o755) + + subprocess.check_call(['systemd-run', '--unit=networkd-test-router.service', + '-p', 'InaccessibleDirectories=-/etc/systemd/network', + '-p', 'InaccessibleDirectories=-/run/systemd/network', + '-p', 'InaccessibleDirectories=-/run/systemd/netif', + '--service-type=notify', script]) + + # wait until devices got created + timeout = 50 + while timeout > 0: + out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router]) + if b'state UP' in out and b'scope global' in out: + break + time.sleep(0.1) + timeout -= 1 + + def shutdown_iface(self): + '''Remove test interface and stop DHCP server''' + + if self.if_router: + subprocess.check_call(['systemctl', 'stop', 'networkd-test-router.service']) + # ensure failed transient unit does not stay around + subprocess.call(['systemctl', 'reset-failed', 'networkd-test-router.service']) + subprocess.check_call(['ip', 'link', 'del', 'dev', self.if_router]) + self.if_router = None + + def print_server_log(self): + '''Print DHCP server log for debugging failures''' + + self.show_journal('networkd-test-router.service') + + @unittest.skip('networkd does not have DHCPv6 server support') + def test_hotplug_dhcp_ip6(self): + pass + + @unittest.skip('networkd does not have DHCPv6 server support') + def test_coldplug_dhcp_ip6(self): + pass + + if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))