hydra-queue-runner: support store URIs declaring an alternate store location

When having a builder like this in `/etc/nix/machines`

    ssh://mfbuild?remote-store=/home/bosch/store

Hydra cannot build there since it tries to pass the entire value to
`ssh(1)` which doesn't work. Also, an alternate store-location is e.g.
used if the user isn't a trusted user on the remote system and thus
cannot use `/nix/store`.

If such a URI is given, Hydra will now add a `--store /home/bosch/store`
to the `ssh`-command to select the appropriate location remotely.
This commit is contained in:
Maximilian Bosch 2022-01-07 17:06:56 +01:00
parent f4e86a3236
commit a18b487403
No known key found for this signature in database
GPG key ID: 091DBF4D1FC46B8E

View file

@ -10,6 +10,7 @@
#include "util.hh" #include "util.hh"
#include "worker-protocol.hh" #include "worker-protocol.hh"
#include "finally.hh" #include "finally.hh"
#include "url.hh"
using namespace nix; using namespace nix;
@ -26,6 +27,25 @@ static void append(Strings & dst, const Strings & src)
dst.insert(dst.end(), src.begin(), src.end()); dst.insert(dst.end(), src.begin(), src.end());
} }
static Strings extraStoreArgs(std::string & machine)
{
Strings result;
try {
auto parsed = parseURL(machine);
if (parsed.scheme != "ssh") {
throw SysError("Currently, only (legacy-)ssh stores are supported!");
}
machine = parsed.authority.value_or("");
auto remoteStore = parsed.query.find("remote-store");
if (remoteStore != parsed.query.end()) {
result = {"--store", shellEscape(remoteStore->second)};
}
} catch (BadURL &) {
// We just try to continue with `machine->sshName` here for backwards compat.
}
return result;
}
static void openConnection(Machine::ptr machine, Path tmpDir, int stderrFD, Child & child) static void openConnection(Machine::ptr machine, Path tmpDir, int stderrFD, Child & child)
{ {
@ -54,7 +74,9 @@ static void openConnection(Machine::ptr machine, Path tmpDir, int stderrFD, Chil
} }
else { else {
pgmName = "ssh"; pgmName = "ssh";
argv = {"ssh", machine->sshName}; auto sshName = machine->sshName;
Strings extraArgs = extraStoreArgs(sshName);
argv = {"ssh", sshName};
if (machine->sshKey != "") append(argv, {"-i", machine->sshKey}); if (machine->sshKey != "") append(argv, {"-i", machine->sshKey});
if (machine->sshPublicHostKey != "") { if (machine->sshPublicHostKey != "") {
Path fileName = tmpDir + "/host-key"; Path fileName = tmpDir + "/host-key";
@ -66,6 +88,7 @@ static void openConnection(Machine::ptr machine, Path tmpDir, int stderrFD, Chil
append(argv, append(argv,
{ "-x", "-a", "-oBatchMode=yes", "-oConnectTimeout=60", "-oTCPKeepAlive=yes" { "-x", "-a", "-oBatchMode=yes", "-oConnectTimeout=60", "-oTCPKeepAlive=yes"
, "--", "nix-store", "--serve", "--write" }); , "--", "nix-store", "--serve", "--write" });
append(argv, extraArgs);
} }
execvp(argv.front().c_str(), (char * *) stringsToCharPtrs(argv).data()); // FIXME: remove cast execvp(argv.front().c_str(), (char * *) stringsToCharPtrs(argv).data()); // FIXME: remove cast