diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-11-21 18:24:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-21 18:24:51 +0100 |
commit | c5066640a1a82bc74f538fe9d2ecc52ea81613b3 (patch) | |
tree | b3e8d885fb1732adc318d17980ca856b06c28ea3 | |
parent | 270f419316758162bfead87608cbaeeb4fd6987e (diff) | |
parent | 89748b0af1aeed4126a6faaf493f7be7230c804a (diff) |
Merge pull request #4701 from martinpitt/networkd-polkit
hostnamed: allow networkd to set the transient hostname
-rw-r--r-- | Makefile.am | 16 | ||||
-rw-r--r-- | src/hostname/systemd-networkd-hostname.pkla | 4 | ||||
-rw-r--r-- | src/hostname/systemd-networkd-hostname.rules | 5 | ||||
-rwxr-xr-x | test/networkd-test.py | 56 |
4 files changed, 76 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am index 47c2ec8a8d..10ce363347 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,6 +55,8 @@ pamconfdir=@pamconfdir@ pkgconfigdatadir=$(datadir)/pkgconfig pkgconfiglibdir=$(libdir)/pkgconfig polkitpolicydir=$(datadir)/polkit-1/actions +polkitrulesdir=$(datadir)/polkit-1/rules.d +polkitpkladir=$(localstatedir)/lib/polkit-1/localauthority/10-vendor.d bashcompletiondir=@bashcompletiondir@ zshcompletiondir=@zshcompletiondir@ rpmmacrosdir=$(prefix)/lib/rpm/macros.d @@ -116,6 +118,8 @@ pkgconfiglib_DATA = polkitpolicy_in_in_files = polkitpolicy_in_files = polkitpolicy_files = +polkitrules_files = +polkitpkla_files = dist_udevrules_DATA = nodist_udevrules_DATA = dist_pkgsysconf_DATA = @@ -4836,8 +4840,16 @@ endif polkitpolicy_in_files += \ src/hostname/org.freedesktop.hostname1.policy.in +polkitrules_files += \ + src/hostname/systemd-networkd-hostname.rules + +polkitpkla_files += \ + src/hostname/systemd-networkd-hostname.pkla + EXTRA_DIST += \ - units/systemd-hostnamed.service.in + units/systemd-hostnamed.service.in \ + src/hostname/systemd-networkd-hostname.rules \ + src/hostname/systemd-networkd-hostname.pkla # ------------------------------------------------------------------------------ dist_systemunit_DATA_busnames += \ @@ -6189,6 +6201,8 @@ if ENABLE_POLKIT nodist_polkitpolicy_DATA = \ $(polkitpolicy_files) \ $(polkitpolicy_in_in_files:.policy.in.in=.policy) +polkitrules_DATA = $(polkitrules_files) +polkitpkla_DATA = $(polkitpkla_files) endif EXTRA_DIST += \ diff --git a/src/hostname/systemd-networkd-hostname.pkla b/src/hostname/systemd-networkd-hostname.pkla new file mode 100644 index 0000000000..345ce617c6 --- /dev/null +++ b/src/hostname/systemd-networkd-hostname.pkla @@ -0,0 +1,4 @@ +[Allow systemd-networkd to set transient hostname] +Identity=unix-user:systemd-network +Action=org.freedesktop.hostname1.set-hostname +ResultAny=yes diff --git a/src/hostname/systemd-networkd-hostname.rules b/src/hostname/systemd-networkd-hostname.rules new file mode 100644 index 0000000000..b7b780da9e --- /dev/null +++ b/src/hostname/systemd-networkd-hostname.rules @@ -0,0 +1,5 @@ +polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.hostname1.set-hostname" && subject.user == "systemd-network") { + return polkit.Result.YES; + } +}); diff --git a/test/networkd-test.py b/test/networkd-test.py index 3091722fc1..a00941095b 100755 --- a/test/networkd-test.py +++ b/test/networkd-test.py @@ -37,6 +37,7 @@ import unittest import tempfile import subprocess import shutil +import socket networkd_active = subprocess.call(['systemctl', 'is-active', '--quiet', 'systemd-networkd']) == 0 @@ -77,6 +78,8 @@ class ClientTestBase: def tearDown(self): self.shutdown_iface() subprocess.call(['systemctl', 'stop', 'systemd-networkd']) + subprocess.call(['ip', 'link', 'del', 'dummy0'], + stderr=subprocess.DEVNULL) def writeConfig(self, fname, contents): os.makedirs(os.path.dirname(fname), exist_ok=True) @@ -121,10 +124,13 @@ DHCP=%s # create interface first, then start networkd self.create_iface(ipv6=ipv6) subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) - else: + elif coldplug is not None: # start networkd first, then create interface subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) self.create_iface(ipv6=ipv6) + else: + # "None" means test sets up interface by itself + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) try: subprocess.check_call([self.networkd_wait_online, '--interface', @@ -194,7 +200,7 @@ DHCP=%s else: self.fail('nameserver 192.168.5.1 not found in ' + RESOLV_CONF) - if not coldplug: + if coldplug is False: # check post-down.d hook self.shutdown_iface() @@ -291,13 +297,15 @@ class DnsmasqClientTest(ClientTestBase, unittest.TestCase): def setUp(self): super().setUp() self.dnsmasq = None + self.iface_mac = 'de:ad:be:ef:47:11' def create_iface(self, ipv6=False, dnsmasq_opts=None): '''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]) + subprocess.check_call(['ip', 'link', 'add', 'name', self.iface, + 'address', self.iface_mac, + 'type', 'veth', 'peer', 'name', self.if_router]) # give our router an IP subprocess.check_call(['ip', 'a', 'flush', 'dev', self.if_router]) @@ -413,6 +421,46 @@ Domains= ~company ~lab''') self.assertRegex(general_log, 'query.*megasearch.net') self.assertNotIn('megasearch.net', vpn_log) + def test_transient_hostname(self): + '''networkd sets transient hostname from DHCP''' + + orig_hostname = socket.gethostname() + self.addCleanup(socket.sethostname, orig_hostname) + # temporarily move /etc/hostname away; restart hostnamed to pick it up + if os.path.exists('/etc/hostname'): + subprocess.check_call(['mount', '--bind', '/dev/null', '/etc/hostname']) + self.addCleanup(subprocess.call, ['umount', '/etc/hostname']) + subprocess.check_call(['systemctl', 'stop', 'systemd-hostnamed.service']) + + self.create_iface(dnsmasq_opts=['--dhcp-host=%s,192.168.5.210,testgreen' % self.iface_mac]) + self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=False', dhcp_mode='ipv4') + + # should have received the fixed IP above + out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface]) + self.assertRegex(out, b'inet 192.168.5.210/24 .* scope global dynamic') + # should have set transient hostname in hostnamed + self.assertIn(b'testgreen', subprocess.check_output(['hostnamectl'])) + # and also applied to the system + self.assertEqual(socket.gethostname(), 'testgreen') + + def test_transient_hostname_with_static(self): + '''transient hostname is not applied if static hostname exists''' + + orig_hostname = socket.gethostname() + self.addCleanup(socket.sethostname, orig_hostname) + if not os.path.exists('/etc/hostname'): + self.writeConfig('/etc/hostname', orig_hostname) + subprocess.check_call(['systemctl', 'stop', 'systemd-hostnamed.service']) + + self.create_iface(dnsmasq_opts=['--dhcp-host=%s,192.168.5.210,testgreen' % self.iface_mac]) + self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=False', dhcp_mode='ipv4') + + # should have received the fixed IP above + out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface]) + self.assertRegex(out, b'inet 192.168.5.210/24 .* scope global dynamic') + # static hostname wins over transient one, thus *not* applied + self.assertEqual(socket.gethostname(), orig_hostname) + class NetworkdClientTest(ClientTestBase, unittest.TestCase): '''Test networkd client against networkd server''' |