Remove the sendDerivation logic from the builder

The queue runner used to special-case `localhost` as a remote builder:
Rather than using the normal remote-build (using the
`cmdBuildDerivation` command), it was using the (generally less
efficient, except when running against localhost) `cmdBuildPaths`
command because the latter didn't require a privileged Nix user (so made
testing easier − allowing to run hydra in a container in particular).

However:
1. this means that the build loop can follow two discint code paths depending
   on the setup, the irony being that the most commonly used one in production
   (the “non-localhost” case) isn't the one used in the testsuite (because all
   the tests run against a local store);
2. It turns out that the “localhost” version is buggy in relatively obvious
   ways − in particular a failure in a fixed-output derivation or a hash
   mismatch isn't reported properly;
3. If the “run in a container” use-case is indeed that important, it can be
   (partially) restored using a chroot store (which wouldn't behave excactly
   the same way of course, but would be more than good-enough for testing)
This commit is contained in:
regnat 2021-02-23 09:50:15 +01:00
parent 107d60027f
commit f602ed0d86

View file

@ -210,7 +210,6 @@ void State::buildRemote(ref<Store> destStore,
}); });
/* Handshake. */ /* Handshake. */
bool sendDerivation = true;
unsigned int remoteVersion; unsigned int remoteVersion;
try { try {
@ -223,12 +222,6 @@ void State::buildRemote(ref<Store> destStore,
remoteVersion = readInt(from); remoteVersion = readInt(from);
if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200) if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)
throw Error("unsupported nix-store --serve protocol version on %1%", machine->sshName); throw Error("unsupported nix-store --serve protocol version on %1%", machine->sshName);
// Always send the derivation to localhost, since it's a
// no-op anyway but we might not be privileged to use
// cmdBuildDerivation (e.g. if we're running in a NixOS
// container).
if (GET_PROTOCOL_MINOR(remoteVersion) >= 1 && !machine->isLocalhost())
sendDerivation = false;
if (GET_PROTOCOL_MINOR(remoteVersion) < 3 && repeats > 0) if (GET_PROTOCOL_MINOR(remoteVersion) < 3 && repeats > 0)
throw Error("machine %1% does not support repeating a build; please upgrade it to Nix 1.12", machine->sshName); throw Error("machine %1% does not support repeating a build; please upgrade it to Nix 1.12", machine->sshName);
@ -253,11 +246,8 @@ void State::buildRemote(ref<Store> destStore,
StorePathSet inputs; StorePathSet inputs;
BasicDerivation basicDrv(*step->drv); BasicDerivation basicDrv(*step->drv);
if (sendDerivation) for (auto & p : step->drv->inputSrcs)
inputs.insert(step->drvPath); inputs.insert(p);
else
for (auto & p : step->drv->inputSrcs)
inputs.insert(p);
for (auto & input : step->drv->inputDrvs) { for (auto & input : step->drv->inputDrvs) {
auto drv2 = localStore->readDerivation(input.first); auto drv2 = localStore->readDerivation(input.first);
@ -313,13 +303,8 @@ void State::buildRemote(ref<Store> destStore,
updateStep(ssBuilding); updateStep(ssBuilding);
if (sendDerivation) { to << cmdBuildDerivation << localStore->printStorePath(step->drvPath);
to << cmdBuildPaths; writeDerivation(to, *localStore, basicDrv);
worker_proto::write(*localStore, to, StorePathSet{step->drvPath});
} else {
to << cmdBuildDerivation << localStore->printStorePath(step->drvPath);
writeDerivation(to, *localStore, basicDrv);
}
to << maxSilentTime << buildTimeout; to << maxSilentTime << buildTimeout;
if (GET_PROTOCOL_MINOR(remoteVersion) >= 2) if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)
to << maxLogSize; to << maxLogSize;
@ -337,83 +322,64 @@ void State::buildRemote(ref<Store> destStore,
} }
result.stopTime = time(0); result.stopTime = time(0);
if (sendDerivation) { result.errorMsg = readString(from);
if (res) { if (GET_PROTOCOL_MINOR(remoteVersion) >= 3) {
result.errorMsg = fmt("%s on %s", readString(from), machine->sshName); result.timesBuilt = readInt(from);
if (res == 100) { result.isNonDeterministic = readInt(from);
result.stepStatus = bsFailed; auto start = readInt(from);
result.canCache = true; auto stop = readInt(from);
} if (start && start) {
else if (res == 101) { /* Note: this represents the duration of a single
result.stepStatus = bsTimedOut; round, rather than all rounds. */
} result.startTime = start;
else { result.stopTime = stop;
result.stepStatus = bsAborted;
result.canRetry = true;
}
return;
} }
result.stepStatus = bsSuccess;
} else {
result.errorMsg = readString(from);
if (GET_PROTOCOL_MINOR(remoteVersion) >= 3) {
result.timesBuilt = readInt(from);
result.isNonDeterministic = readInt(from);
auto start = readInt(from);
auto stop = readInt(from);
if (start && start) {
/* Note: this represents the duration of a single
round, rather than all rounds. */
result.startTime = start;
result.stopTime = stop;
}
}
switch ((BuildResult::Status) res) {
case BuildResult::Built:
result.stepStatus = bsSuccess;
break;
case BuildResult::Substituted:
case BuildResult::AlreadyValid:
result.stepStatus = bsSuccess;
result.isCached = true;
break;
case BuildResult::PermanentFailure:
result.stepStatus = bsFailed;
result.canCache = true;
result.errorMsg = "";
break;
case BuildResult::InputRejected:
case BuildResult::OutputRejected:
result.stepStatus = bsFailed;
result.canCache = true;
break;
case BuildResult::TransientFailure:
result.stepStatus = bsFailed;
result.canRetry = true;
result.errorMsg = "";
break;
case BuildResult::TimedOut:
result.stepStatus = bsTimedOut;
result.errorMsg = "";
break;
case BuildResult::MiscFailure:
result.stepStatus = bsAborted;
result.canRetry = true;
break;
case BuildResult::LogLimitExceeded:
result.stepStatus = bsLogLimitExceeded;
break;
case BuildResult::NotDeterministic:
result.stepStatus = bsNotDeterministic;
result.canRetry = false;
result.canCache = true;
break;
default:
result.stepStatus = bsAborted;
break;
}
if (result.stepStatus != bsSuccess) return;
} }
switch ((BuildResult::Status) res) {
case BuildResult::Built:
result.stepStatus = bsSuccess;
break;
case BuildResult::Substituted:
case BuildResult::AlreadyValid:
result.stepStatus = bsSuccess;
result.isCached = true;
break;
case BuildResult::PermanentFailure:
result.stepStatus = bsFailed;
result.canCache = true;
result.errorMsg = "";
break;
case BuildResult::InputRejected:
case BuildResult::OutputRejected:
result.stepStatus = bsFailed;
result.canCache = true;
break;
case BuildResult::TransientFailure:
result.stepStatus = bsFailed;
result.canRetry = true;
result.errorMsg = "";
break;
case BuildResult::TimedOut:
result.stepStatus = bsTimedOut;
result.errorMsg = "";
break;
case BuildResult::MiscFailure:
result.stepStatus = bsAborted;
result.canRetry = true;
break;
case BuildResult::LogLimitExceeded:
result.stepStatus = bsLogLimitExceeded;
break;
case BuildResult::NotDeterministic:
result.stepStatus = bsNotDeterministic;
result.canRetry = false;
result.canCache = true;
break;
default:
result.stepStatus = bsAborted;
break;
}
if (result.stepStatus != bsSuccess) return;
result.errorMsg = ""; result.errorMsg = "";