1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
| | #! /usr/bin/env avocado-runner-avocado-classless
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright Red Hat
# Author: David Gibson <david@gibson.dropbear.id.au>
"""
Test A Simple Socket Transport
dhcp.py - Helpers for testing DHCP
"""
import contextlib
import ipaddress
import os
import tempfile
from avocado_classless.test import assert_eq, test_output
from tasst.address import IpiAllocator, TEST_NET_1
from tasst.nstool import unshare_site
DHCLIENT = '/sbin/dhclient'
@contextlib.contextmanager
def dhclient(site, ifname, ipv='4'):
site.require_cmds(DHCLIENT)
with tempfile.TemporaryDirectory() as tmpdir:
pidfile = os.path.join(tmpdir, 'dhclient.pid')
leasefile = os.path.join(tmpdir, 'dhclient.leases')
# We need '-nc' because we may be running with
# capabilities but not UID 0. Without -nc dhclient drops
# capabilities before invoking dhclient-script, so it's
# unable to actually configure the interface
opts = f'-{ipv} -v -nc -pf {pidfile} -lf {leasefile} {ifname}'
with site.daemon(f'{DHCLIENT} {opts}', sudo=True, pidfile=pidfile):
yield
def test_dhcp(ifname, expected_addr, gateway, mtu):
def dec(setupfn):
def test_addr(setup):
with setup as site, dhclient(site, ifname):
(actual_addr,) = site.addrs(ifname, family='inet',
scope='global')
assert_eq(actual_addr.ip, expected_addr)
def test_route(setup):
with setup as site, dhclient(site, ifname):
(defroute,) = site.routes4(dst='default')
assert_eq(ipaddress.ip_address(defroute['gateway']), gateway)
def test_mtu(setup):
with setup as site, dhclient(site, ifname):
assert_eq(site.mtu(ifname), mtu)
return test_output(test_addr, test_route, test_mtu)(setupfn)
return dec
DHCPD = 'dhcpd'
SUBNET = TEST_NET_1
ipa = IpiAllocator(SUBNET)
(SERVER_IP4,) = ipa.next_ipis()
(CLIENT_IP4,) = ipa.next_ipis()
IFNAME = 'clientif'
@contextlib.contextmanager
def setup_dhcpd_common(ifname, server_ifname):
with unshare_site('client', '-Un') as client, \
unshare_site('server', '-n', parent=client, sudo=True) as server:
server.require_cmds(DHCPD)
client.veth(ifname, server_ifname, server)
with tempfile.TemporaryDirectory() as tmpdir:
yield (client, server, tmpdir)
@test_dhcp(IFNAME, CLIENT_IP4.ip, SERVER_IP4.ip, 1500)
@contextlib.contextmanager
def setup_dhcpd():
server_ifname = 'serverif'
with setup_dhcpd_common(IFNAME, server_ifname) as (client, server, tmpdir):
# Configure dhcpd
confpath = os.path.join(tmpdir, 'dhcpd.conf')
open(confpath, 'w', encoding='UTF-8').write(
f'''subnet {SUBNET.network_address} netmask {SUBNET.netmask} {{
option routers {SERVER_IP4.ip};
range {CLIENT_IP4.ip} {CLIENT_IP4.ip};
}}'''
)
pidfile = os.path.join(tmpdir, 'dhcpd.pid')
leasepath = os.path.join(tmpdir, 'dhcpd.leases')
open(leasepath, 'wb').write(b'')
server.ifup('lo')
server.ifup(server_ifname, SERVER_IP4)
opts = f'-f -d -4 -cf {confpath} -lf {leasepath} -pf {pidfile}'
server.fg(f'{DHCPD} -t {opts}') # test config
with server.bg(f'{DHCPD} {opts}', sudo=True, ignore_status=True,
pidfile=pidfile):
# Configure the client
client.ifup('lo')
yield client
|