summaryrefslogtreecommitdiff
path: root/selftest
diff options
context:
space:
mode:
authorTim Beale <timbeale@catalyst.net.nz>2019-02-26 15:54:34 +1300
committerAndrew Bartlett <abartlet@samba.org>2019-05-31 05:18:20 +0000
commit5635a7ce2fe348a3ed89ff39a02f9db135424367 (patch)
tree18498bdfaa51e6d74fdaac253c88d1b873f52bac /selftest
parent8e3bc591733c868320a0f91d3f3e3943bd95b92e (diff)
downloadsamba-5635a7ce2fe348a3ed89ff39a02f9db135424367.tar.gz
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>
Diffstat (limited to 'selftest')
-rw-r--r--selftest/ns/README65
-rwxr-xr-xselftest/ns/add_bridge_iface.sh22
-rwxr-xr-xselftest/ns/create_bridge.sh19
-rwxr-xr-xselftest/ns/start_in_ns.sh56
4 files changed, 162 insertions, 0 deletions
diff --git a/selftest/ns/README b/selftest/ns/README
new file mode 100644
index 00000000000..e9e9d0665c7
--- /dev/null
+++ b/selftest/ns/README
@@ -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.
+
diff --git a/selftest/ns/add_bridge_iface.sh b/selftest/ns/add_bridge_iface.sh
new file mode 100755
index 00000000000..da9d53a5987
--- /dev/null
+++ b/selftest/ns/add_bridge_iface.sh
@@ -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
+
diff --git a/selftest/ns/create_bridge.sh b/selftest/ns/create_bridge.sh
new file mode 100755
index 00000000000..9766cd8a565
--- /dev/null
+++ b/selftest/ns/create_bridge.sh
@@ -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
+
+
diff --git a/selftest/ns/start_in_ns.sh b/selftest/ns/start_in_ns.sh
new file mode 100755
index 00000000000..5831a0b2e24
--- /dev/null
+++ b/selftest/ns/start_in_ns.sh
@@ -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