Merge pull request #30021 from yuwata/dhcp-client-id-cleanups
dhcp-server: save bound leases to persistent storage, and load it on start
This commit is contained in:
@@ -888,8 +888,10 @@ class NetworkdClientTest(ClientTestBase, unittest.TestCase):
|
||||
set -eu
|
||||
mkdir -p /run/systemd/network
|
||||
mkdir -p /run/systemd/netif
|
||||
mkdir -p /var/lib/systemd/network
|
||||
mount -t tmpfs none /run/systemd/network
|
||||
mount -t tmpfs none /run/systemd/netif
|
||||
mount -t tmpfs none /var/lib/systemd/network
|
||||
[ ! -e /run/dbus ] || mount -t tmpfs none /run/dbus
|
||||
# create router/client veth pair
|
||||
cat <<EOF >/run/systemd/network/50-test.netdev
|
||||
@@ -917,6 +919,10 @@ DNS=192.168.5.1
|
||||
{dhopts}
|
||||
EOF
|
||||
|
||||
# For the networkd instance invoked below cannot support varlink connection.
|
||||
# Hence, 'networkctl persistent-storage yes' cannot be used.
|
||||
touch /run/systemd/netif/persistent-storage-ready
|
||||
|
||||
# run networkd as in systemd-networkd.service
|
||||
exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ {{ s/^.*=//; s/^[@+-]//; s/^!*//; p}}')
|
||||
'''.format(ifr=self.if_router,
|
||||
@@ -930,6 +936,7 @@ exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ {{ s/^.*=/
|
||||
'-p', 'InaccessibleDirectories=-/etc/systemd/network',
|
||||
'-p', 'InaccessibleDirectories=-/run/systemd/network',
|
||||
'-p', 'InaccessibleDirectories=-/run/systemd/netif',
|
||||
'-p', 'InaccessibleDirectories=-/var/lib/systemd/network',
|
||||
'--service-type=notify', script])
|
||||
|
||||
# wait until devices got created
|
||||
|
||||
@@ -51,18 +51,17 @@ radvd_pid_file = '/run/networkd-ci/test-radvd.pid'
|
||||
|
||||
systemd_lib_paths = ['/usr/lib/systemd', '/lib/systemd']
|
||||
which_paths = ':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
|
||||
systemd_source_dir = None
|
||||
|
||||
networkd_bin = shutil.which('systemd-networkd', path=which_paths)
|
||||
resolved_bin = shutil.which('systemd-resolved', path=which_paths)
|
||||
timesyncd_bin = shutil.which('systemd-timesyncd', path=which_paths)
|
||||
udevd_bin = shutil.which('systemd-udevd', path=which_paths)
|
||||
wait_online_bin = shutil.which('systemd-networkd-wait-online', path=which_paths)
|
||||
networkctl_bin = shutil.which('networkctl', path=which_paths)
|
||||
resolvectl_bin = shutil.which('resolvectl', path=which_paths)
|
||||
timedatectl_bin = shutil.which('timedatectl', path=which_paths)
|
||||
udevadm_bin = shutil.which('udevadm', path=which_paths)
|
||||
systemd_udev_rules_build_dir = None
|
||||
build_dir = None
|
||||
source_dir = None
|
||||
|
||||
use_valgrind = False
|
||||
valgrind_cmd = ''
|
||||
@@ -365,12 +364,13 @@ def clear_networkd_conf_dropins():
|
||||
rm_rf(networkd_conf_dropin_dir)
|
||||
|
||||
def setup_systemd_udev_rules():
|
||||
if not systemd_udev_rules_build_dir:
|
||||
if not build_dir:
|
||||
return
|
||||
|
||||
mkdir_p(udev_rules_dir)
|
||||
|
||||
for path in [systemd_udev_rules_build_dir, os.path.join(systemd_source_dir, "rules.d")]:
|
||||
for path in [build_dir, source_dir]:
|
||||
path = os.path.join(path, "rules.d")
|
||||
print(f"Copying udev rules from {path} to {udev_rules_dir}")
|
||||
|
||||
for rule in os.listdir(path):
|
||||
@@ -378,6 +378,9 @@ def setup_systemd_udev_rules():
|
||||
continue
|
||||
cp(os.path.join(path, rule), udev_rules_dir)
|
||||
|
||||
def clear_networkd_state_files():
|
||||
rm_rf('/var/lib/systemd/network/')
|
||||
|
||||
def copy_udev_rule(*rules):
|
||||
"""Copy udev rules"""
|
||||
mkdir_p(udev_rules_dir)
|
||||
@@ -412,11 +415,12 @@ def create_unit_dropin(unit, contents):
|
||||
f.write('\n'.join(contents))
|
||||
|
||||
def create_service_dropin(service, command, additional_settings=None):
|
||||
drop_in = [
|
||||
'[Service]',
|
||||
'ExecStart=',
|
||||
f'ExecStart=!!{valgrind_cmd}{command}',
|
||||
]
|
||||
drop_in = ['[Service]']
|
||||
if command:
|
||||
drop_in += [
|
||||
'ExecStart=',
|
||||
f'ExecStart=!!{valgrind_cmd}{command}',
|
||||
]
|
||||
if enable_debug:
|
||||
drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
|
||||
if asan_options:
|
||||
@@ -444,6 +448,87 @@ def create_service_dropin(service, command, additional_settings=None):
|
||||
|
||||
create_unit_dropin(f'{service}.service', drop_in)
|
||||
|
||||
def setup_system_units():
|
||||
if build_dir:
|
||||
mkdir_p('/run/systemd/system/')
|
||||
|
||||
for unit in [
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket',
|
||||
'systemd-networkd-persistent-storage.service',
|
||||
'systemd-resolved.service',
|
||||
'systemd-timesyncd.service',
|
||||
'systemd-udevd.service',
|
||||
]:
|
||||
for path in [build_dir, source_dir]:
|
||||
fullpath = os.path.join(os.path.join(path, "units"), unit)
|
||||
if os.path.exists(fullpath):
|
||||
print(f"Copying unit file from {fullpath} to /run/systemd/system/")
|
||||
cp(fullpath, '/run/systemd/system/')
|
||||
break
|
||||
|
||||
create_service_dropin('systemd-networkd', networkd_bin,
|
||||
['[Service]',
|
||||
'Restart=no',
|
||||
'Environment=SYSTEMD_NETWORK_TEST_MODE=yes',
|
||||
'[Unit]',
|
||||
'StartLimitIntervalSec=0'])
|
||||
create_service_dropin('systemd-resolved', resolved_bin)
|
||||
create_service_dropin('systemd-timesyncd', timesyncd_bin)
|
||||
|
||||
# TODO: also run udevd with sanitizers, valgrind, or coverage
|
||||
create_unit_dropin(
|
||||
'systemd-udevd.service',
|
||||
[
|
||||
'[Service]',
|
||||
'ExecStart=',
|
||||
f'ExecStart=!!@{udevadm_bin} systemd-udevd',
|
||||
]
|
||||
)
|
||||
create_unit_dropin(
|
||||
'systemd-networkd.socket',
|
||||
[
|
||||
'[Unit]',
|
||||
'StartLimitIntervalSec=0',
|
||||
]
|
||||
)
|
||||
create_unit_dropin(
|
||||
'systemd-networkd-persistent-storage.service',
|
||||
[
|
||||
'[Unit]',
|
||||
'StartLimitIntervalSec=0',
|
||||
'[Service]',
|
||||
'ExecStart=',
|
||||
f'ExecStart={networkctl_bin} persistent-storage yes',
|
||||
'ExecStop=',
|
||||
f'ExecStop={networkctl_bin} persistent-storage no'
|
||||
]
|
||||
)
|
||||
|
||||
check_output('systemctl daemon-reload')
|
||||
print(check_output('systemctl cat systemd-networkd.service'))
|
||||
print(check_output('systemctl cat systemd-networkd-persistent-storage.service'))
|
||||
print(check_output('systemctl cat systemd-resolved.service'))
|
||||
print(check_output('systemctl cat systemd-timesyncd.service'))
|
||||
print(check_output('systemctl cat systemd-udevd.service'))
|
||||
check_output('systemctl restart systemd-resolved.service')
|
||||
check_output('systemctl restart systemd-timesyncd.service')
|
||||
check_output('systemctl restart systemd-udevd.service')
|
||||
|
||||
def clear_system_units():
|
||||
def rm_unit(name):
|
||||
rm_f(f'/run/systemd/system/{name}')
|
||||
rm_rf(f'/run/systemd/system/{name}.d')
|
||||
|
||||
rm_unit('systemd-networkd.service')
|
||||
rm_unit('systemd-networkd.socket')
|
||||
rm_unit('systemd-networkd-persistent-storage.service')
|
||||
rm_unit('systemd-resolved.service')
|
||||
rm_unit('systemd-timesyncd.service')
|
||||
rm_unit('systemd-udevd.service')
|
||||
check_output('systemctl daemon-reload')
|
||||
check_output('systemctl restart systemd-udevd.service')
|
||||
|
||||
def link_exists(link):
|
||||
return call_quiet(f'ip link show {link}') == 0
|
||||
|
||||
@@ -830,6 +915,7 @@ def tear_down_common():
|
||||
# 6. remove configs
|
||||
clear_network_units()
|
||||
clear_networkd_conf_dropins()
|
||||
clear_networkd_state_files()
|
||||
|
||||
# 7. flush settings
|
||||
flush_fou_ports()
|
||||
@@ -843,6 +929,7 @@ def setUpModule():
|
||||
|
||||
clear_network_units()
|
||||
clear_networkd_conf_dropins()
|
||||
clear_networkd_state_files()
|
||||
clear_udev_rules()
|
||||
|
||||
setup_systemd_udev_rules()
|
||||
@@ -855,58 +942,18 @@ def setUpModule():
|
||||
save_routing_policy_rules()
|
||||
save_timezone()
|
||||
|
||||
create_service_dropin('systemd-networkd', networkd_bin,
|
||||
['[Service]',
|
||||
'Restart=no',
|
||||
'Environment=SYSTEMD_NETWORK_TEST_MODE=yes',
|
||||
'[Unit]',
|
||||
'StartLimitIntervalSec=0'])
|
||||
create_service_dropin('systemd-resolved', resolved_bin)
|
||||
create_service_dropin('systemd-timesyncd', timesyncd_bin)
|
||||
|
||||
# TODO: also run udevd with sanitizers, valgrind, or coverage
|
||||
#create_service_dropin('systemd-udevd', udevd_bin,
|
||||
# f'{udevadm_bin} control --reload --timeout 0')
|
||||
create_unit_dropin(
|
||||
'systemd-udevd.service',
|
||||
[
|
||||
'[Service]',
|
||||
'ExecStart=',
|
||||
f'ExecStart=!!@{udevd_bin} systemd-udevd',
|
||||
]
|
||||
)
|
||||
create_unit_dropin(
|
||||
'systemd-networkd.socket',
|
||||
[
|
||||
'[Unit]',
|
||||
'StartLimitIntervalSec=0',
|
||||
]
|
||||
)
|
||||
|
||||
check_output('systemctl daemon-reload')
|
||||
print(check_output('systemctl cat systemd-networkd.service'))
|
||||
print(check_output('systemctl cat systemd-resolved.service'))
|
||||
print(check_output('systemctl cat systemd-timesyncd.service'))
|
||||
print(check_output('systemctl cat systemd-udevd.service'))
|
||||
check_output('systemctl restart systemd-resolved.service')
|
||||
check_output('systemctl restart systemd-timesyncd.service')
|
||||
check_output('systemctl restart systemd-udevd.service')
|
||||
setup_system_units()
|
||||
|
||||
def tearDownModule():
|
||||
rm_rf(networkd_ci_temp_dir)
|
||||
clear_udev_rules()
|
||||
clear_network_units()
|
||||
clear_networkd_conf_dropins()
|
||||
clear_networkd_state_files()
|
||||
|
||||
restore_timezone()
|
||||
|
||||
rm_rf('/run/systemd/system/systemd-networkd.service.d')
|
||||
rm_rf('/run/systemd/system/systemd-networkd.socket.d')
|
||||
rm_rf('/run/systemd/system/systemd-resolved.service.d')
|
||||
rm_rf('/run/systemd/system/systemd-timesyncd.service.d')
|
||||
rm_rf('/run/systemd/system/systemd-udevd.service.d')
|
||||
check_output('systemctl daemon-reload')
|
||||
check_output('systemctl restart systemd-udevd.service')
|
||||
clear_system_units()
|
||||
restore_active_units()
|
||||
|
||||
class Utilities():
|
||||
@@ -5687,8 +5734,20 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, 'NTP: 192.168.5.1\n *192.168.5.11')
|
||||
|
||||
output = networkctl_status('veth-peer')
|
||||
print(output)
|
||||
self.assertRegex(output, "Offered DHCP leases: 192.168.5.[0-9]*")
|
||||
|
||||
networkctl_reconfigure('veth-peer')
|
||||
self.wait_online('veth-peer:routable')
|
||||
|
||||
for _ in range(10):
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth-peer', env=env)
|
||||
if 'Offered DHCP leases: 192.168.5.' in output:
|
||||
break
|
||||
time.sleep(.2)
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_dhcp_server_null_server_address(self):
|
||||
copy_network_unit('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server-null-server-address.network')
|
||||
start_networkd()
|
||||
@@ -7464,15 +7523,6 @@ if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
|
||||
parser.add_argument('--source-dir', help='Path to source dir/git tree', dest='source_dir')
|
||||
parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
|
||||
parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
|
||||
parser.add_argument('--timesyncd', help='Path to systemd-timesyncd', dest='timesyncd_bin')
|
||||
parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
|
||||
parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
|
||||
parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
|
||||
parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
|
||||
parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
|
||||
parser.add_argument('--udevadm', help='Path to udevadm', dest='udevadm_bin')
|
||||
parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
|
||||
parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
|
||||
parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
|
||||
@@ -7482,45 +7532,21 @@ if __name__ == '__main__':
|
||||
ns, unknown_args = parser.parse_known_args(namespace=unittest)
|
||||
|
||||
if ns.build_dir:
|
||||
if ns.networkd_bin or ns.resolved_bin or ns.timesyncd_bin or ns.udevd_bin or \
|
||||
ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin or ns.udevadm_bin:
|
||||
print('WARNING: --networkd, --resolved, --timesyncd, --udevd, --wait-online, --networkctl, --resolvectl, --timedatectl, or --udevadm options are ignored when --build-dir is specified.')
|
||||
networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
|
||||
resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
|
||||
timesyncd_bin = os.path.join(ns.build_dir, 'systemd-timesyncd')
|
||||
udevd_bin = os.path.join(ns.build_dir, 'udevadm')
|
||||
wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
|
||||
networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
|
||||
resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
|
||||
timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
|
||||
udevadm_bin = os.path.join(ns.build_dir, 'udevadm')
|
||||
systemd_udev_rules_build_dir = os.path.join(ns.build_dir, 'rules.d')
|
||||
else:
|
||||
if ns.networkd_bin:
|
||||
networkd_bin = ns.networkd_bin
|
||||
if ns.resolved_bin:
|
||||
resolved_bin = ns.resolved_bin
|
||||
if ns.timesyncd_bin:
|
||||
timesyncd_bin = ns.timesyncd_bin
|
||||
if ns.udevd_bin:
|
||||
udevd_bin = ns.udevd_bin
|
||||
if ns.wait_online_bin:
|
||||
wait_online_bin = ns.wait_online_bin
|
||||
if ns.networkctl_bin:
|
||||
networkctl_bin = ns.networkctl_bin
|
||||
if ns.resolvectl_bin:
|
||||
resolvectl_bin = ns.resolvectl_bin
|
||||
if ns.timedatectl_bin:
|
||||
timedatectl_bin = ns.timedatectl_bin
|
||||
if ns.udevadm_bin:
|
||||
udevadm_bin = ns.udevadm_bin
|
||||
build_dir = ns.build_dir
|
||||
|
||||
if ns.source_dir:
|
||||
systemd_source_dir = ns.source_dir
|
||||
source_dir = ns.source_dir
|
||||
else:
|
||||
systemd_source_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../"))
|
||||
if not os.path.exists(os.path.join(systemd_source_dir, "meson_options.txt")):
|
||||
raise RuntimeError(f"{systemd_source_dir} doesn't appear to be a systemd source tree")
|
||||
source_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../"))
|
||||
assert os.path.exists(os.path.join(source_dir, "meson_options.txt")), f"{source_dir} doesn't appear to be a systemd source tree."
|
||||
|
||||
use_valgrind = ns.use_valgrind
|
||||
enable_debug = ns.enable_debug
|
||||
|
||||
Reference in New Issue
Block a user