diff options
Diffstat (limited to 'src/build-remote/build-remote.cc')
-rw-r--r-- | src/build-remote/build-remote.cc | 105 |
1 files changed, 63 insertions, 42 deletions
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 4b7a24d03e9a..6e05e165545d 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -16,6 +16,7 @@ #include "serialise.hh" #include "store-api.hh" #include "derivations.hh" +#include "local-store.hh" using namespace nix; using std::cin; @@ -41,24 +42,33 @@ int main (int argc, char * * argv) return handleExceptions(argv[0], [&]() { initNix(); + logger = makeJSONLogger(*logger); + /* Ensure we don't get any SSH passphrase or host key popups. */ unsetenv("DISPLAY"); unsetenv("SSH_ASKPASS"); - if (argc != 6) + if (argc != 2) throw UsageError("called without required arguments"); - auto store = openStore(); + verbosity = (Verbosity) std::stoll(argv[1]); + + FdSource source(STDIN_FILENO); + + /* Read the parent's settings. */ + while (readInt(source)) { + auto name = readString(source); + auto value = readString(source); + settings.set(name, value); + } + + settings.maxBuildJobs.set("1"); // hack to make tests with local?root= work - auto localSystem = argv[1]; - settings.maxSilentTime = std::stoll(argv[2]); - settings.buildTimeout = std::stoll(argv[3]); - verbosity = (Verbosity) std::stoll(argv[4]); - settings.builders = argv[5]; + auto store = openStore().cast<LocalStore>(); /* It would be more appropriate to use $XDG_RUNTIME_DIR, since that gets cleared on reboot, but it wouldn't work on macOS. */ - currentLoad = settings.nixStateDir + "/current-load"; + currentLoad = store->stateDir + "/current-load"; std::shared_ptr<Store> sshStore; AutoCloseFD bestSlotLock; @@ -73,18 +83,20 @@ int main (int argc, char * * argv) string drvPath; string storeUri; - for (string line; getline(cin, line);) { - auto tokens = tokenizeString<std::vector<string>>(line); - auto sz = tokens.size(); - if (sz != 3 && sz != 4) - throw Error("invalid build hook line '%1%'", line); - auto amWilling = tokens[0] == "1"; - auto neededSystem = tokens[1]; - drvPath = tokens[2]; - auto requiredFeatures = sz == 3 ? - std::set<string>{} : - tokenizeString<std::set<string>>(tokens[3], ","); - auto canBuildLocally = amWilling && (neededSystem == localSystem); + + while (true) { + + try { + auto s = readString(source); + if (s != "try") return; + } catch (EndOfFile &) { return; } + + auto amWilling = readInt(source); + auto neededSystem = readString(source); + source >> drvPath; + auto requiredFeatures = readStrings<std::set<std::string>>(source); + + auto canBuildLocally = amWilling && (neededSystem == settings.thisSystem); /* Error ignored here, will be caught later */ mkdir(currentLoad.c_str(), 0777); @@ -99,7 +111,7 @@ int main (int argc, char * * argv) Machine * bestMachine = nullptr; unsigned long long bestLoad = 0; for (auto & m : machines) { - debug("considering building on '%s'", m.storeUri); + debug("considering building on remote machine '%s'", m.storeUri); if (m.enabled && std::find(m.systemTypes.begin(), m.systemTypes.end(), @@ -162,9 +174,15 @@ int main (int argc, char * * argv) try { - Store::Params storeParams{{"max-connections", "1"}, {"log-fd", "4"}}; - if (bestMachine->sshKey != "") - storeParams["ssh-key"] = bestMachine->sshKey; + Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri)); + + Store::Params storeParams; + if (hasPrefix(storeUri, "ssh://")) { + storeParams["max-connections"] ="1"; + storeParams["log-fd"] = "4"; + if (bestMachine->sshKey != "") + storeParams["ssh-key"] = bestMachine->sshKey; + } sshStore = openStore(bestMachine->storeUri, storeParams); sshStore->connect(); @@ -182,32 +200,34 @@ int main (int argc, char * * argv) } connected: - std::cerr << "# accept\n"; - string line; - if (!getline(cin, line)) - throw Error("hook caller didn't send inputs"); + std::cerr << "# accept\n" << storeUri << "\n"; - auto inputs = tokenizeString<PathSet>(line); - if (!getline(cin, line)) - throw Error("hook caller didn't send outputs"); - - auto outputs = tokenizeString<PathSet>(line); + auto inputs = readStrings<PathSet>(source); + auto outputs = readStrings<PathSet>(source); AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri) + ".upload-lock", true); - auto old = signal(SIGALRM, handleAlarm); - alarm(15 * 60); - if (!lockFile(uploadLock.get(), ltWrite, true)) - printError("somebody is hogging the upload lock for '%s', continuing..."); - alarm(0); - signal(SIGALRM, old); - copyPaths(store, ref<Store>(sshStore), inputs, NoRepair, NoCheckSigs); + { + Activity act(*logger, lvlTalkative, actUnknown, fmt("waiting for the upload lock to '%s'", storeUri)); + + auto old = signal(SIGALRM, handleAlarm); + alarm(15 * 60); + if (!lockFile(uploadLock.get(), ltWrite, true)) + printError("somebody is hogging the upload lock for '%s', continuing..."); + alarm(0); + signal(SIGALRM, old); + } + + { + Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri)); + copyPaths(store, ref<Store>(sshStore), inputs, NoRepair, NoCheckSigs); + } + uploadLock = -1; - BasicDerivation drv(readDerivation(drvPath)); + BasicDerivation drv(readDerivation(store->realStoreDir + "/" + baseNameOf(drvPath))); drv.inputSrcs = inputs; - printError("building '%s' on '%s'", drvPath, storeUri); auto result = sshStore->buildDerivation(drvPath, drv); if (!result.success()) @@ -218,6 +238,7 @@ connected: if (!store->isValidPath(path)) missing.insert(path); if (!missing.empty()) { + Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri)); setenv("NIX_HELD_LOCKS", concatStringsSep(" ", missing).c_str(), 1); /* FIXME: ugly */ copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs); } |