1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

selftest: Add helper scripts to run selftest in namespaces

This adds the underlying scripts, but they are not actually hooked up to
the selftest code yet, and so are not actually used.

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Tim Beale 2019-02-26 15:54:34 +13:00 committed by Andrew Bartlett
parent 8e3bc59173
commit 5635a7ce2f
4 changed files with 162 additions and 0 deletions

65
selftest/ns/README Normal file
View File

@ -0,0 +1,65 @@
The scripts in this directory are experimental and are used to create testenvs
in separate linux namespaces. This avoids the need for socket-wrapper.
What are Namespaces
===================
Namespaces allow the kernel to segregate its system resources (files, CPU,
etc), so that different processes only see the set of resources they are
allowed to use. There are several different types of namespace: network,
user, process, file, IPC, and so on.
Key points to grasp are:
* Each type of namespace gets managed separately by the kernel, i.e. process
namespaces are managed separately to network namespaces, which are separate
to user namespaces. These scripts give each testenv its own network namespace,
but otherwise they all still share the same user/process/etc namespace.
(In future, we may want to give each testenv its own process and user
namespace, to better mimic a production DC).
* Namespaces are created using the 'unshare' utility. The new selftest
namespaces are anonymous/nameless, and so the different namespaces are
identified by the PID of the processes running within the namespace
(typically samba).
* Linux supports nesting namespaces within namespaces. In this case, each
testenv DC has its own network namespace, which is a child of the overarching
selftest namespace (which itself is a child of whatever namespace you run
'make test' from - usually this would be the root namespace).
How does it work?
=================
Normally when 'make test' is run, every testenv uses a 127.0.0.x IP address
and socket-wrapper passes the packets between them.
With namespaces, we can use real IP addresses and have the packets pass through
the kernel's IP stack normally, as it forwards them between namespaces.
We use veth interfaces for this. veth is a type of virtual interface supported
by the kernel. veth interfaces come in pairs, and act as a tunnel - any packets
sent on a veth interface simply end up as received packets on the pair veth
interface.
We create a new veth interface pair for each testenv, and use them to connect
up the namespaces. One end of the veth pair is added to the main selftest
namespace, and the other end is added to a new namespace that we'll run
samba in. E.g.
selftest.pl veth21-br ------------------------ veth21 samba (ad_dc_ntvfs)
10.0.0.11 10.0.0.21
Namespace 1 Namespace 2
However, we need to run multiple different testenvs and have them talk to
each other. So to do this, we need a bridge interface ('selftest0') to connect
up the namespaces, which essentially just acts as a hub. So connecting together
multiple testenvs looks more like this:
selftest.pl +-- veth21-br ------------------------ veth21 samba (ad_dc_ntvfs)
| 10.0.0.21
selftest0 --+ Namespace 2
10.0.0.11 |
+-- veth22-br ------------------------ veth22 samba (vampire_dc)
10.0.0.22
Namespace 1 Namespace 3
The veth interfaces are named vethX and vethX-br, where X is the
SOCKET_WRAPPER_DEFAULT_IFACE for the testenv. The vethX-br interface is always
added to the selftest0 bridge interface.

22
selftest/ns/add_bridge_iface.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/sh
#
# Configures the interfaces needed for communication between namespaces.
# This handles the bridge-end of the veth pair.
interface=$1
# the main bridge interface is called 'selftest0' (although in future we may
# want to segregate the different domains by using different bridges)
bridge=$2
# we need to wait for the child namespace to start up and add the new
# interface back to our new namespace
while ! ip link show $interface > /dev/null 2>&1
do
sleep 0.1
echo "Waiting for $interface to be created..."
done
# bring the bridge-end of the link up and add it to the bridge
ip link set dev $interface up
ip link set $interface master $bridge

19
selftest/ns/create_bridge.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
# creates a bridge interface (i.e. 'selftest0') that connects together the
# veth interfaces for the various testenvs
br_name=$1
ip_addr=$2
ipv6_addr=$3
# make sure the loopback is up (needed for pinging between namespaces, etc)
ip link set dev lo up
# create the bridge interface and enable it
ip link add $br_name type bridge
ip addr add $ip_addr/24 dev $br_name
ip addr add $ipv6_addr/112 dev $br_name
ip link set $br_name up

56
selftest/ns/start_in_ns.sh Executable file
View File

@ -0,0 +1,56 @@
#!/bin/sh
#
# Starts samba in a separate namespace. This gets passed the interface/IP
# to use, as well as the Samba command to run. The whole script gets run
# (via unshare) in a separate namespace.
# the first 3 args are our interface-name, parent-PID, and a exports file
# containing environment variables ($SERVER, $SERVER_IP, etc)
interface=$1
exports_file=$2
parent_pid=$3
# we write the testenv environment variables to file, which makes it easier
# to work out the $SERVER, $SERVER_IP, etc
. $exports_file
# The namespaces we use are anonymous, which means other processes would need
# to use our PID to access the new namespace
echo "-------------------------------------------------------------"
echo "Created namespace for $NETBIOSNAME"
echo "To communicate with this testenv, use: nsenter -t $$ --net sh"
echo "To copy its environment variables, use: . $exports_file"
echo "-------------------------------------------------------------"
# the rest of the args are the samba command to run
shift 3
SAMBA_CMD=$@
# make sure namespace loopback is up (it's needed for ping, etc)
ip link set dev lo up
# Create the interfaces needed for communication between namespaces.
# We use a veth pair, which acts as a tunnel between the namespaces.
# One end of the veth link is added to a common bridge in the top-level (i.e.
# selftest) namespace, and the other end is added to the testenv's namespace.
# This means each testenv DC is in its own namespace, but they can talk to
# each other via the common bridge interface.
# The new veth interfaces are named "vethX" and "vethX-br", where
# X = the testenv IP (i.e. Samba::get_interface()). E.g. ad_dc = veth30,
# and veth30-br.
# The "vethX" interface will live in the new testenv's namespace.
# The "vethX-br" end is added to the bridge in the main selftest namespace.
ip link add dev $interface-br type veth peer name $interface
# move the bridge end of the link back into the parent namespace.
ip link set $interface-br netns $parent_pid
# configure our IP address and bring the interface up
ip addr add $SERVER_IP/24 dev $interface
# Note that samba can't bind to the IPv6 address while DAD is in progress,
# so we use 'nodad' when configuring the address
ip addr add $SERVER_IPV6/112 dev $interface nodad
ip link set dev $interface up
# start samba
$SAMBA_CMD