#! /usr/bin/python3 # SPDX-License-Identifier: GPL-2.0-or-later # # tasst - Test A Simple Socket Transport # library of test helpers for passt & pasta # # tasst/dhcpv6.py - Helpers for testing DHCPv6 # # Copyright Red Hat # Author: David Gibson import ipaddress import os from tasst import Tasst, TasstSubData from tasst.address import IpiAllocator, TEST_NET6_TASST_A from tasst.nstool import UnshareSite class BaseDhcpv6Tasst(Tasst): """ Test DHCPv6 behaviour. :avocado: disable """ DHCLIENT = '/sbin/dhclient' def subsetup(self, site, ifname, addr): site.require_cmds(self.DHCLIENT) pidfile = os.path.join(self.workdir, 'dhclient.pid') leasefile = os.path.join(self.workdir, '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 site.fg('{} -6 -v -nc -pf {} -lf {} {}' .format(self.DHCLIENT, pidfile, leasefile, ifname), sudo=True) Tasst.subsetup(self, BaseDhcpv6Tasst, TasstSubData(site=site, ifname=ifname, addr=addr)) def test_addr(self): sub = self.get_subsetup(BaseDhcpv6Tasst) addrs = [a.ip for a in sub.site.addrs(sub.ifname, family='inet6', scope='global')] self.assertIn(sub.addr, addrs) # Might also have a SLAAC address class MetaDhcpv6Tasst(BaseDhcpv6Tasst): """Ugly workaround for https://github.com/avocado-framework/avocado/issues/5680. Explicitly apply the "meta" tag to inherited tests :avocado: disable :avocado: tags=meta """ def test_addr(self): super().test_addr() class Dhcpd6Tasst(MetaDhcpv6Tasst): """ :avocado: tags=meta """ DHCPD = 'dhcpd' SUBNET = TEST_NET6_TASST_A def setUp(self): super().setUp() ifname = 'clientif' server_ifname = 'serverif' self.client = UnshareSite(self.__class__.__name__ + '.client', '-Un') self.server = UnshareSite(self.__class__.__name__ + '.server', '-n', parent=self.client, sudo=True) self.server.require_cmds(self.DHCPD) self.client.veth(ifname, server_ifname, self.server) # Allocate IPs, and sort out link local addressing ipa = IpiAllocator(self.SUBNET) (server_ip6,) = ipa.next_ipis() (client_ip6,) = ipa.next_ipis() self.server.ifup('lo') self.server.ifup(server_ifname, server_ip6) self.client.ifup('lo') self.client.ifup(ifname) (server_ip6_ll,) = self.server.addr_wait(server_ifname, family='inet6', scope='link') # Configure the DHCP server confpath = os.path.join(self.workdir, 'dhcpd.conf') open(confpath, 'w').write(''' subnet6 {} {{ range6 {} {}; }} '''.format(self.SUBNET, client_ip6.ip, client_ip6.ip)) self.pidpath = os.path.join(self.workdir, 'dhcpd.pid') leasepath = os.path.join(self.workdir, 'dhcpd.leases') open(leasepath, 'w').write('') opts = ('-f -d -6 -cf {} -lf {} -pf {}'.format(confpath, leasepath, self.pidpath)) self.server.fg('{} -t {}'.format(self.DHCPD, opts)) # test config self.dhcpd = self.server.bg('{} {}'.format(self.DHCPD, opts), sudo=True) # Configure the client BaseDhcpv6Tasst.subsetup(self, self.client, ifname, client_ip6.ip) def tearDown(self): pid = int(open(self.pidpath).read()) self.server.fg('kill {}'.format(pid)) status = self.dhcpd.wait() self.server.close() self.client.close() super().tearDown()