tstest/natlab/vmtest, cmd/tta: add TestTaildrop

Add a vmtest that brings up two Ubuntu nodes, each behind its own
EasyNAT, joined to the tailnet. The sender pushes a small file via
"tailscale file cp" and the receiver fetches it via "tailscale file
get --wait", asserting that the filename and contents round-trip
unchanged.

To make Taildrop work in vmtest, three small pieces were needed:

The Linux/FreeBSD cloud-init now starts tailscaled with --statedir as
well as --state=mem:, so the daemon has a VarRoot to host Taildrop's
incoming-files directory. State itself remains in-memory (so nothing
persists across reboots); only the var-root scratch space is on disk.

vmtest.New grows a variadic EnvOption parameter and a SameTailnetUser
helper. When the option is passed, Start sets AllNodesSameUser=true
on the embedded testcontrol.Server. Cross-node Taildrop requires the
sender and receiver to share a Tailnet user (or have an explicit
PeerCapabilityFileSharingTarget granted between them, which we don't
plumb here), so TestTaildrop opts in. Existing tests don't.

cmd/tta gains /taildrop-send and /taildrop-recv handlers that wrap
"tailscale file cp" and "tailscale file get --wait", plus
Env.SendTaildropFile and Env.RecvTaildropFile helpers in vmtest that
drive them.

Updates #13038

Change-Id: I8f5f70f88106e6e2ee07780dd46fe00f8efcfdf1
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2026-04-28 17:26:10 +00:00
committed by Brad Fitzpatrick
parent 4b8e0ede6d
commit ec7b11d986
4 changed files with 222 additions and 5 deletions
+8 -3
View File
@@ -120,8 +120,11 @@ func (e *Env) generateLinuxUserData(n *Node) string {
ud.WriteString(" - [\"sysctl\", \"-w\", \"net.ipv6.conf.all.forwarding=1\"]\n")
}
// Start tailscaled in the background.
ud.WriteString(" - [\"/bin/sh\", \"-c\", \"/usr/local/bin/tailscaled --state=mem: &\"]\n")
// Start tailscaled in the background. --statedir provides a VarRoot so
// features like Taildrop (which needs a place to stash incoming files)
// have a directory to work with.
ud.WriteString(" - [\"mkdir\", \"-p\", \"/var/lib/tailscale\"]\n")
ud.WriteString(" - [\"/bin/sh\", \"-c\", \"/usr/local/bin/tailscaled --state=mem: --statedir=/var/lib/tailscale &\"]\n")
ud.WriteString(" - [\"sleep\", \"2\"]\n")
// Start tta (Tailscale Test Agent).
@@ -173,7 +176,9 @@ func (e *Env) generateFreeBSDUserData(n *Node) string {
// Start tailscaled and tta in the background.
// Set PATH to include /usr/local/bin so that tta can find "tailscale"
// (TTA uses exec.Command("tailscale", ...) without a full path).
ud.WriteString(" - \"export PATH=/usr/local/bin:$PATH && /usr/local/bin/tailscaled --state=mem: &\"\n")
// --statedir provides a VarRoot so features like Taildrop have a directory.
ud.WriteString(" - \"mkdir -p /var/lib/tailscale\"\n")
ud.WriteString(" - \"export PATH=/usr/local/bin:$PATH && /usr/local/bin/tailscaled --state=mem: --statedir=/var/lib/tailscale &\"\n")
ud.WriteString(" - \"sleep 2\"\n")
// Start tta (Tailscale Test Agent).