-
Notifications
You must be signed in to change notification settings - Fork 4
Description
In cdist-ungleich an interesting discussion has come up in #331:
how can we safely and atomically transfer file from the local machine to the remote machine?
The scope of this problem is not limited to the __file type. It also applies to other types in cdist-conf, e.g. __config_file, __dot_file, __staged_file (via __file), __download and possibly others.
I think the discussion is worth pursuing as a properly designed solution will benefit all cdist users (who doesn't use __file?).
Requirements to a solution:
- use non-predictable temporary file names (no race conditions),
- should not fail if temporary directory is size constrained,
- must not leave the system in a broken state if the destination has insufficient space for the file,
- must not leave temp files in
$destination(think of applications usinginclude *configuration), - replacement of the
$destinationmust be atomic (in the sense of made in one SSH connection).
(Please extend if I forgot something.)
Proposals:
Common to all proposals is the division between code-local and code-remote: code-local copies the file to a remote temp location, code-remote moves the remote temp file to $destination and ensures the attributes are set correctly.
Copy to $TMPDIR using mktemp(1), then move to $destination.
This is how __file has worked in the past, albeit using mktemp -u.
pros: uses non-predictable file names (if mktemp is used on the target), no temp files in $destination.
cons: fails if the file is large and $TMPDIR is size constrained (e.g. tmpfs), may leave the system in a broken state if insufficient space in $destination.
Copy to remote ${__object}/files/tempfile, then move to $destination.
This solution uses completely predictable file names, but I don't think this is a problem because cdist's run directory is root-owned and 0700.
Also the remote $__object directory is used for a single cdist run only, so there shouldn't be any collisions possible.
pros: no temp files in $destination.
cons: may fail if cdist's run directory is space-constained, may leave the system in a broken state if insufficient space in $destination.
Copy to $destination.tmp.XXXXXX, then move to $destination.
Idea:
In code-local:
- Allocate a random temp file in
$destinationon the target safely, usingmktemp, - copy file to allocated temp file,
- store temporary file name in remote's
$__object.
Then in code-remote:
- Set file attributes,
- move from
$destination.tmp.XXXXXX(as stored in$__object) to$destination.
pros: non-predictable temp names, does not use $TMPDIR, does not fail if $destination has insufficient space (can't copy file in the first place)
cons: may leave temp files in $destination if code-* fails for some reason.
Decisions
-
Can we rely on
mktemp(1)?
cdist is supposed to only rely on POSIX features andmktemp(1)isn't defined by POSIX.
Furthermoremktemp(1)has no standardized interface. An invocation that works fine on Linux may fail or produce an unecpected result on e.g. OpenBSD.Or could we hack our own
mktempusing/dev/random,trandset -C?