public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob d86df2de7b4dd9338938b1a656997014950fed4b 4045 bytes (raw)

  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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
 
#! /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

import exeter

from . import address, nstool


DHCLIENT = '/sbin/dhclient'


@contextlib.contextmanager
def dhclient(snh, ifname, ipv='4'):
    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', f'{pidfile}',
                '-lf', f'{leasefile}', f'{ifname}']
        snh.fg(f'{DHCLIENT}', *opts, capable=True)
        yield
        snh.fg(f'{DHCLIENT}', '-x', '-pf', f'{pidfile}', capable=True)


class DhcpTestScenario:
    def __init__(self, *, client, ifname, addr, gateway, mtu):
        self.client = client
        self.ifname = ifname
        self.addr = addr
        self.gateway = gateway
        self.mtu = mtu


def test_dhcp_addr(setup):
    with setup as scn, dhclient(scn.client, scn.ifname):
        (actual_addr,) = scn.client.addrs(scn.ifname,
                                          family='inet', scope='global')
        exeter.assert_eq(actual_addr.ip, scn.addr)


def test_dhcp_route(setup):
    with setup as scn, dhclient(scn.client, scn.ifname):
        (defroute,) = scn.client.routes4(dst='default')
        exeter.assert_eq(ipaddress.ip_address(defroute['gateway']),
                         scn.gateway)


def test_dhcp_mtu(setup):
    with setup as scn, dhclient(scn.client, scn.ifname):
        exeter.assert_eq(scn.client.mtu(scn.ifname), scn.mtu)


DHCP_TESTS = [test_dhcp_addr, test_dhcp_route, test_dhcp_mtu]


def dhcp_tests(setup):
    for t in DHCP_TESTS:
        testid = f'{setup.__qualname__}|{t.__qualname__}'
        exeter.register_pipe(testid, setup, t)


DHCPD = 'dhcpd'
SUBNET = address.TEST_NET_1
ipa = address.IpiAllocator(SUBNET)
(SERVER_IP4,) = ipa.next_ipis()
(CLIENT_IP4,) = ipa.next_ipis()
IFNAME = 'clientif'


@contextlib.contextmanager
def setup_dhcpd_common(ifname, server_ifname):
    with nstool.unshare_snh('client', '-Un') as client, \
         nstool.unshare_snh('server', '-n',
                            parent=client, capable=True) as server:
        client.veth(ifname, server_ifname, server)

        with tempfile.TemporaryDirectory() as tmpdir:
            yield (client, server, tmpdir)


@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', '-d', '-4', '-cf', f'{confpath}',
                '-lf', f'{leasepath}', '-pf', f'{pidfile}']
        server.fg(f'{DHCPD}', '-t', *opts)  # test config
        with server.bg(f'{DHCPD}', *opts, capable=True, check=False) as dhcpd:
            # Configure the client
            client.ifup('lo')
            yield DhcpTestScenario(client=client, ifname=IFNAME,
                                   addr=CLIENT_IP4.ip,
                                   gateway=SERVER_IP4.ip, mtu=1500)
            dhcpd.terminate()


dhcp_tests(setup_dhcpd)

debug log:

solving d86df2de ...
found d86df2de in https://archives.passt.top/passt-dev/20240805123701.1720730-21-david@gibson.dropbear.id.au/

applying [1/1] https://archives.passt.top/passt-dev/20240805123701.1720730-21-david@gibson.dropbear.id.au/
diff --git a/test/tasst/dhcp.py b/test/tasst/dhcp.py
new file mode 100644
index 00000000..d86df2de

Checking patch test/tasst/dhcp.py...
Applied patch test/tasst/dhcp.py cleanly.

index at:
100644 d86df2de7b4dd9338938b1a656997014950fed4b	test/tasst/dhcp.py

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).