Compare commits

...

16 Commits

Author SHA1 Message Date
John Ericson
2e136dd6a3 WIP: Avoid custom logic copying outputs from the remote builder
We need a replacement for the nar member logic, however. And maybe also
a test that fails until this is fixed (this one should not be passing).
2025-02-18 14:08:30 -05:00
John Ericson
a873a128e4 Avoid custom logic to copy inputs to the remote builder 2025-02-18 14:08:30 -05:00
John Ericson
4a4a0f901c Use LegacySSHStore
In https://github.com/NixOS/nix/pull/10748 it is extended with
everything we need.
2025-02-18 14:07:42 -05:00
John Ericson
881462bb4e Merge pull request #1447 from NixOS/newer-2.6
Bump to newer 2.26.* Nix version
2025-02-18 13:00:40 -05:00
John Ericson
af72b694d8 Bump to newer 2.26.* Nix version
Needed one more thing before trying out using `LegacySSHStore` directly.

Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/674a87462cb93f605d4fbeef607d3453e7e5a7d8?narHash=sha256-TBoHqnIdVWhsBcL05vO2B1hSl9m//5Mz2NU%2BPMk3h3Y%3D' (2025-02-16)
  → 'github:NixOS/nix/e310c19a1aeb1ce1ed4d41d5ab2d02db596e0918?narHash=sha256-q/RgA4bB7zWai4oPySq9mch7qH14IEeom2P64SXdqHs%3D' (2025-02-18)
2025-02-18 12:43:31 -05:00
John Ericson
c92342d12f Merge pull request #1446 from NixOS/newer-2.6
Bump to newer 2.26.* Nix version
2025-02-16 19:10:10 -05:00
John Ericson
df07670a21 Bump to newer 2.26.* Nix version
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/970942f45836172fda410a638853382952189eb9?narHash=sha256-jGFuyYKJjJZsBRoi7ZcaVKt1OYxusz/ld1HA7VD2w/0%3D' (2025-02-12)
  → 'github:NixOS/nix/674a87462cb93f605d4fbeef607d3453e7e5a7d8?narHash=sha256-TBoHqnIdVWhsBcL05vO2B1hSl9m//5Mz2NU%2BPMk3h3Y%3D' (2025-02-16)
2025-02-16 18:44:32 -05:00
John Ericson
51944a5fa5 Merge pull request #1443 from NixOS/nix-2.26
Nix 2.26
2025-02-13 22:13:32 -05:00
John Ericson
341b2f1309 Update build system to depend on Nix 2.26 2025-02-13 21:54:35 -05:00
John Ericson
4dc0f11379 Update flake.nix for Nix 2.26
Flake lock file updates:

• Removed input 'libgit2'
• Updated input 'nix':
    'github:NixOS/nix/d652513e4519ed4eb48c92f8670e5a71c7793fc3?narHash=sha256-mIpJgIwPS4o4xYhN1B%2B/fHESEXoxpu6nVoZTzZ0MfTg%3D' (2025-02-12)
  → 'github:NixOS/nix/970942f45836172fda410a638853382952189eb9?narHash=sha256-jGFuyYKJjJZsBRoi7ZcaVKt1OYxusz/ld1HA7VD2w/0%3D' (2025-02-12)
• Removed input 'nix/libgit2'
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/6d4fd5a93d7bc953ffa4dcd6d53ad7056a71eff7?narHash=sha256-1dZLPw%2BnlFQzzswfyTxW%2B8VF1AJ4ZvoYvLTjlHiz1SA%3D' (2025-02-13)
  → 'github:nix-community/nix-eval-jobs/4b392b284877d203ae262e16af269f702df036bc?narHash=sha256-3wIReAqdTALv39gkWXLMZQvHyBOc3yPkWT2ZsItxedY%3D' (2025-02-14)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/dbebdd67a6006bb145d98c8debf9140ac7e651d0?narHash=sha256-Xc9lEtentPCEtxc/F1e6jIZsd4MPDYv4Kugl9WtXlz0%3D' (2024-09-18)
  → 'github:NixOS/nixpkgs/97a719c9f0a07923c957cf51b20b329f9fb9d43f?narHash=sha256-1o1qR0KYozYGRrnqytSpAhVBYLNBHX%2BLv6I39zGRzKM%3D' (2025-02-13)
2025-02-13 21:54:31 -05:00
John Ericson
ea09952b7e Merge pull request #1442 from NixOS/clean-up-flake-lockfile
Clean up flake lockfile stuff
2025-02-13 20:52:40 -05:00
John Ericson
81d21979ef Clean up flake lockfile stuff
The `flake = false;` for `nix-eval-jobs` didn't fully take before.

Flake lock file updates:

• Removed input 'nix-eval-jobs/flake-parts'
• Removed input 'nix-eval-jobs/flake-parts/nixpkgs-lib'
• Removed input 'nix-eval-jobs/nix-github-actions'
• Removed input 'nix-eval-jobs/nixpkgs'
• Removed input 'nix-eval-jobs/treefmt-nix'
• Removed input 'nix-eval-jobs/treefmt-nix/nixpkgs'
2025-02-13 20:23:08 -05:00
John Ericson
0ed9a82912 Merge pull request #1441 from NixOS/nix-2.25
Nix 2.25
2025-02-13 19:53:07 -05:00
John Ericson
80241fc8be Make code change necessary for building with Nix 2.25 2025-02-13 19:10:09 -05:00
John Ericson
4347833f45 Rework to synchronize deps
Bypass `nix-eval-job`'s flake, and just call-package it, for
fine-grained control.
2025-02-13 19:03:37 -05:00
John Ericson
8835cbd10f flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/a7fdef6858dd45b9d7bda7c92324c63faee7f509?narHash=sha256-XFznzb8L4SdUm9u%2Bw3DPpMWJhffuv%2B/6%2BaiVl00slns%3D' (2024-09-19)
  → 'github:NixOS/nix/d652513e4519ed4eb48c92f8670e5a71c7793fc3?narHash=sha256-mIpJgIwPS4o4xYhN1B%2B/fHESEXoxpu6nVoZTzZ0MfTg%3D' (2025-02-12)
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/889ea1406736b53cf165b6c28398aae3969418d1?narHash=sha256-3wwtKpS5tUBdjaGeSia7CotonbiRB6K5Kp0dsUt3nzU%3D' (2024-12-10)
  → 'github:nix-community/nix-eval-jobs/6d4fd5a93d7bc953ffa4dcd6d53ad7056a71eff7?narHash=sha256-1dZLPw%2BnlFQzzswfyTxW%2B8VF1AJ4ZvoYvLTjlHiz1SA%3D' (2025-02-13)
2025-02-13 18:46:36 -05:00
8 changed files with 117 additions and 345 deletions

95
flake.lock generated
View File

@@ -1,51 +1,10 @@
{ {
"nodes": { "nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nix-eval-jobs",
"nixpkgs"
]
},
"locked": {
"lastModified": 1722555600,
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"libgit2": {
"flake": false,
"locked": {
"lastModified": 1715853528,
"narHash": "sha256-J2rCxTecyLbbDdsyBWn9w7r3pbKRMkI9E7RvRgAqBdY=",
"owner": "libgit2",
"repo": "libgit2",
"rev": "36f7e21ad757a3dacc58cf7944329da6bc1d6e96",
"type": "github"
},
"original": {
"owner": "libgit2",
"ref": "v1.8.1",
"repo": "libgit2",
"type": "github"
}
},
"nix": { "nix": {
"inputs": { "inputs": {
"flake-compat": [], "flake-compat": [],
"flake-parts": [], "flake-parts": [],
"git-hooks-nix": [], "git-hooks-nix": [],
"libgit2": [
"libgit2"
],
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@@ -53,88 +12,58 @@
"nixpkgs-regression": [] "nixpkgs-regression": []
}, },
"locked": { "locked": {
"lastModified": 1726787955, "lastModified": 1739899400,
"narHash": "sha256-XFznzb8L4SdUm9u+w3DPpMWJhffuv+/6+aiVl00slns=", "narHash": "sha256-q/RgA4bB7zWai4oPySq9mch7qH14IEeom2P64SXdqHs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nix", "repo": "nix",
"rev": "a7fdef6858dd45b9d7bda7c92324c63faee7f509", "rev": "e310c19a1aeb1ce1ed4d41d5ab2d02db596e0918",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "2.24-maintenance", "ref": "2.26-maintenance",
"repo": "nix", "repo": "nix",
"type": "github" "type": "github"
} }
}, },
"nix-eval-jobs": { "nix-eval-jobs": {
"inputs": { "flake": false,
"flake-parts": "flake-parts",
"nix-github-actions": [],
"nixpkgs": [
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"locked": { "locked": {
"lastModified": 1733814344, "lastModified": 1739500569,
"narHash": "sha256-3wwtKpS5tUBdjaGeSia7CotonbiRB6K5Kp0dsUt3nzU=", "narHash": "sha256-3wIReAqdTALv39gkWXLMZQvHyBOc3yPkWT2ZsItxedY=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-eval-jobs", "repo": "nix-eval-jobs",
"rev": "889ea1406736b53cf165b6c28398aae3969418d1", "rev": "4b392b284877d203ae262e16af269f702df036bc",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "release-2.24",
"repo": "nix-eval-jobs", "repo": "nix-eval-jobs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1726688310, "lastModified": 1739461644,
"narHash": "sha256-Xc9lEtentPCEtxc/F1e6jIZsd4MPDYv4Kugl9WtXlz0=", "narHash": "sha256-1o1qR0KYozYGRrnqytSpAhVBYLNBHX+Lv6I39zGRzKM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "dbebdd67a6006bb145d98c8debf9140ac7e651d0", "rev": "97a719c9f0a07923c957cf51b20b329f9fb9d43f",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-24.05-small", "ref": "nixos-24.11-small",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"libgit2": "libgit2",
"nix": "nix", "nix": "nix",
"nix-eval-jobs": "nix-eval-jobs", "nix-eval-jobs": "nix-eval-jobs",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nix-eval-jobs",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723303070,
"narHash": "sha256-krGNVA30yptyRonohQ+i9cnK+CfCpedg6z3qzqVJcTs=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "14c092e0326de759e16b37535161b3cb9770cea3",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@@ -1,25 +1,25 @@
{ {
description = "A Nix-based continuous build system"; description = "A Nix-based continuous build system";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05-small"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11-small";
inputs.libgit2 = { url = "github:libgit2/libgit2/v1.8.1"; flake = false; }; inputs.nix = {
inputs.nix.url = "github:NixOS/nix/2.24-maintenance"; url = "github:NixOS/nix/2.26-maintenance";
inputs.nix.inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.nix.inputs.libgit2.follows = "libgit2";
inputs.nix-eval-jobs.url = "github:nix-community/nix-eval-jobs/release-2.24"; # hide nix dev tooling from our lock file
inputs.nix-eval-jobs.inputs.nixpkgs.follows = "nixpkgs"; inputs.flake-parts.follows = "";
inputs.git-hooks-nix.follows = "";
inputs.nixpkgs-regression.follows = "";
inputs.nixpkgs-23-11.follows = "";
inputs.flake-compat.follows = "";
};
# hide nix dev tooling from our lock file inputs.nix-eval-jobs = {
inputs.nix.inputs.flake-parts.follows = ""; url = "github:nix-community/nix-eval-jobs";
inputs.nix.inputs.git-hooks-nix.follows = ""; # We want to control the deps precisely
inputs.nix.inputs.nixpkgs-regression.follows = ""; flake = false;
inputs.nix.inputs.nixpkgs-23-11.follows = ""; };
inputs.nix.inputs.flake-compat.follows = "";
# hide nix-eval-jobs dev tooling from our lock file
inputs.nix-eval-jobs.inputs.nix-github-actions.follows = "";
outputs = { self, nixpkgs, nix, nix-eval-jobs, ... }: outputs = { self, nixpkgs, nix, nix-eval-jobs, ... }:
let let
@@ -30,9 +30,9 @@
# A Nixpkgs overlay that provides a 'hydra' package. # A Nixpkgs overlay that provides a 'hydra' package.
overlays.default = final: prev: { overlays.default = final: prev: {
nix-eval-jobs = final.callPackage nix-eval-jobs {};
hydra = final.callPackage ./package.nix { hydra = final.callPackage ./package.nix {
inherit (nixpkgs.lib) fileset; inherit (nixpkgs.lib) fileset;
nix-eval-jobs = nix-eval-jobs.packages.${final.system}.default;
rawSrc = self; rawSrc = self;
nix-perl-bindings = final.nixComponents.nix-perl-bindings; nix-perl-bindings = final.nixComponents.nix-perl-bindings;
}; };
@@ -74,11 +74,19 @@
}); });
packages = forEachSystem (system: { packages = forEachSystem (system: {
nix-eval-jobs = nixpkgs.legacyPackages.${system}.callPackage nix-eval-jobs {
nix = nix.packages.${system}.nix;
};
hydra = nixpkgs.legacyPackages.${system}.callPackage ./package.nix { hydra = nixpkgs.legacyPackages.${system}.callPackage ./package.nix {
inherit (nixpkgs.lib) fileset; inherit (nixpkgs.lib) fileset;
nix-eval-jobs = nix-eval-jobs.packages.${system}.default; inherit (self.packages.${system}) nix-eval-jobs;
rawSrc = self; rawSrc = self;
nix = nix.packages.${system}.nix; inherit (nix.packages.${system})
nix-util
nix-store
nix-main
nix-cli
;
nix-perl-bindings = nix.hydraJobs.perlBindings.${system}; nix-perl-bindings = nix.hydraJobs.perlBindings.${system};
}; };
default = self.packages.${system}.hydra; default = self.packages.${system}.hydra;

View File

@@ -8,22 +8,22 @@ project('hydra', 'cpp',
], ],
) )
nix_util_dep = dependency('nix-util', required: true)
nix_store_dep = dependency('nix-store', required: true) nix_store_dep = dependency('nix-store', required: true)
nix_main_dep = dependency('nix-main', required: true) nix_main_dep = dependency('nix-main', required: true)
nix_expr_dep = dependency('nix-expr', required: true)
nix_flake_dep = dependency('nix-flake', required: true)
nix_cmd_dep = dependency('nix-cmd', required: true)
# Nix need extra flags not provided in its pkg-config files. # Nix need extra flags not provided in its pkg-config files.
nix_dep = declare_dependency( nix_dep = declare_dependency(
dependencies: [ dependencies: [
nix_util_dep,
nix_store_dep, nix_store_dep,
nix_main_dep, nix_main_dep,
nix_expr_dep,
nix_flake_dep,
nix_cmd_dep,
], ],
compile_args: ['-include', 'nix/config.h'], compile_args: [
'-include', 'nix/config-util.hh',
'-include', 'nix/config-store.hh',
'-include', 'nix/config-main.hh',
],
) )
pqxx_dep = dependency('libpqxx', required: true) pqxx_dep = dependency('libpqxx', required: true)

View File

@@ -8,7 +8,10 @@
, perlPackages , perlPackages
, nix , nix-util
, nix-store
, nix-main
, nix-cli
, nix-perl-bindings , nix-perl-bindings
, git , git
@@ -162,7 +165,7 @@ stdenv.mkDerivation (finalAttrs: {
nukeReferences nukeReferences
pkg-config pkg-config
mdbook mdbook
nix nix-cli
perlDeps perlDeps
perl perl
unzip unzip
@@ -172,7 +175,9 @@ stdenv.mkDerivation (finalAttrs: {
libpqxx libpqxx
openssl openssl
libxslt libxslt
nix nix-util
nix-store
nix-main
perlDeps perlDeps
perl perl
boost boost
@@ -199,13 +204,14 @@ stdenv.mkDerivation (finalAttrs: {
glibcLocales glibcLocales
libressl.nc libressl.nc
python3 python3
nix-cli
]; ];
hydraPath = lib.makeBinPath ( hydraPath = lib.makeBinPath (
[ [
subversion subversion
openssh openssh
nix nix-cli
coreutils coreutils
findutils findutils
pixz pixz
@@ -266,7 +272,7 @@ stdenv.mkDerivation (finalAttrs: {
--prefix PATH ':' $out/bin:$hydraPath \ --prefix PATH ':' $out/bin:$hydraPath \
--set HYDRA_RELEASE ${version} \ --set HYDRA_RELEASE ${version} \
--set HYDRA_HOME $out/libexec/hydra \ --set HYDRA_HOME $out/libexec/hydra \
--set NIX_RELEASE ${nix.name or "unknown"} \ --set NIX_RELEASE ${nix-cli.name or "unknown"} \
--set NIX_EVAL_JOBS_RELEASE ${nix-eval-jobs.name or "unknown"} --set NIX_EVAL_JOBS_RELEASE ${nix-eval-jobs.name or "unknown"}
done done
''; '';
@@ -274,5 +280,5 @@ stdenv.mkDerivation (finalAttrs: {
dontStrip = true; dontStrip = true;
meta.description = "Build of Hydra on ${stdenv.system}"; meta.description = "Build of Hydra on ${stdenv.system}";
passthru = { inherit perlDeps nix; }; passthru = { inherit perlDeps; };
}) })

View File

@@ -9,13 +9,10 @@
#include "path.hh" #include "path.hh"
#include "legacy-ssh-store.hh" #include "legacy-ssh-store.hh"
#include "serve-protocol.hh" #include "serve-protocol.hh"
#include "serve-protocol-impl.hh"
#include "state.hh" #include "state.hh"
#include "current-process.hh" #include "current-process.hh"
#include "processes.hh" #include "processes.hh"
#include "util.hh" #include "util.hh"
#include "serve-protocol.hh"
#include "serve-protocol-impl.hh"
#include "ssh.hh" #include "ssh.hh"
#include "finally.hh" #include "finally.hh"
#include "url.hh" #include "url.hh"
@@ -39,108 +36,6 @@ bool ::Machine::isLocalhost() const
namespace nix::build_remote { namespace nix::build_remote {
static std::unique_ptr<SSHMaster::Connection> openConnection(
::Machine::ptr machine, SSHMaster & master)
{
Strings command = {"nix-store", "--serve", "--write"};
if (machine->isLocalhost()) {
command.push_back("--builders");
command.push_back("");
} else {
auto remoteStore = machine->storeUri.params.find("remote-store");
if (remoteStore != machine->storeUri.params.end()) {
command.push_back("--store");
command.push_back(shellEscape(remoteStore->second));
}
}
auto ret = master.startCommand(std::move(command), {
"-a", "-oBatchMode=yes", "-oConnectTimeout=60", "-oTCPKeepAlive=yes"
});
// XXX: determine the actual max value we can use from /proc.
// FIXME: Should this be upstreamed into `startCommand` in Nix?
int pipesize = 1024 * 1024;
fcntl(ret->in.get(), F_SETPIPE_SZ, &pipesize);
fcntl(ret->out.get(), F_SETPIPE_SZ, &pipesize);
return ret;
}
static void copyClosureTo(
::Machine::Connection & conn,
Store & destStore,
const StorePathSet & paths,
SubstituteFlag useSubstitutes = NoSubstitute)
{
StorePathSet closure;
destStore.computeFSClosure(paths, closure);
/* Send the "query valid paths" command with the "lock" option
enabled. This prevents a race where the remote host
garbage-collect paths that are already there. Optionally, ask
the remote host to substitute missing paths. */
// FIXME: substitute output pollutes our build log
/* Get back the set of paths that are already valid on the remote
host. */
auto present = conn.queryValidPaths(
destStore, true, closure, useSubstitutes);
if (present.size() == closure.size()) return;
auto sorted = destStore.topoSortPaths(closure);
StorePathSet missing;
for (auto i = sorted.rbegin(); i != sorted.rend(); ++i)
if (!present.count(*i)) missing.insert(*i);
printMsg(lvlDebug, "sending %d missing paths", missing.size());
std::unique_lock<std::timed_mutex> sendLock(conn.machine->state->sendLock,
std::chrono::seconds(600));
conn.to << ServeProto::Command::ImportPaths;
destStore.exportPaths(missing, conn.to);
conn.to.flush();
if (readInt(conn.from) != 1)
throw Error("remote machine failed to import closure");
}
// FIXME: use Store::topoSortPaths().
static StorePaths reverseTopoSortPaths(const std::map<StorePath, UnkeyedValidPathInfo> & paths)
{
StorePaths sorted;
StorePathSet visited;
std::function<void(const StorePath & path)> dfsVisit;
dfsVisit = [&](const StorePath & path) {
if (!visited.insert(path).second) return;
auto info = paths.find(path);
auto references = info == paths.end() ? StorePathSet() : info->second.references;
for (auto & i : references)
/* Don't traverse into paths that don't exist. That can
happen due to substitutes for non-existent paths. */
if (i != path && paths.count(i))
dfsVisit(i);
sorted.push_back(path);
};
for (auto & i : paths)
dfsVisit(i.first);
return sorted;
}
static std::pair<Path, AutoCloseFD> openLogFile(const std::string & logDir, const StorePath & drvPath) static std::pair<Path, AutoCloseFD> openLogFile(const std::string & logDir, const StorePath & drvPath)
{ {
std::string base(drvPath.to_string()); std::string base(drvPath.to_string());
@@ -203,13 +98,13 @@ static BasicDerivation sendInputs(
auto now1 = std::chrono::steady_clock::now(); auto now1 = std::chrono::steady_clock::now();
/* Copy the input closure. */ /* Copy the input closure. */
if (conn.machine->isLocalhost()) { copyClosure(
StorePathSet closure; destStore,
destStore.computeFSClosure(basicDrv.inputSrcs, closure); conn.machine->isLocalhost() ? localStore : *conn.store,
copyPaths(destStore, localStore, closure, NoRepair, NoCheckSigs, NoSubstitute); basicDrv.inputSrcs,
} else { NoRepair,
copyClosureTo(conn, destStore, basicDrv.inputSrcs, Substitute); NoCheckSigs,
} Substitute);
auto now2 = std::chrono::steady_clock::now(); auto now2 = std::chrono::steady_clock::now();
@@ -228,7 +123,7 @@ static BuildResult performBuild(
counter & nrStepsBuilding counter & nrStepsBuilding
) )
{ {
conn.putBuildDerivationRequest(localStore, drvPath, drv, options); auto kont = conn.store->buildDerivationAsync(drvPath, drv, options);
BuildResult result; BuildResult result;
@@ -237,7 +132,10 @@ static BuildResult performBuild(
startTime = time(0); startTime = time(0);
{ {
MaintainCount<counter> mc(nrStepsBuilding); MaintainCount<counter> mc(nrStepsBuilding);
result = ServeProto::Serialise<BuildResult>::read(localStore, conn); result = kont();
// Without proper call-once functions, we need to manually
// delete after calling.
kont = {};
} }
stopTime = time(0); stopTime = time(0);
@@ -253,7 +151,7 @@ static BuildResult performBuild(
// If the protocol was too old to give us `builtOutputs`, initialize // If the protocol was too old to give us `builtOutputs`, initialize
// it manually by introspecting the derivation. // it manually by introspecting the derivation.
if (GET_PROTOCOL_MINOR(conn.remoteVersion) < 6) if (GET_PROTOCOL_MINOR(conn.store->getProtocol()) < 6)
{ {
// If the remote is too old to handle CA derivations, we cant get this // If the remote is too old to handle CA derivations, we cant get this
// far anyways // far anyways
@@ -278,55 +176,6 @@ static BuildResult performBuild(
return result; return result;
} }
static void copyPathFromRemote(
::Machine::Connection & conn,
NarMemberDatas & narMembers,
Store & localStore,
Store & destStore,
const ValidPathInfo & info
)
{
/* Receive the NAR from the remote and add it to the
destination store. Meanwhile, extract all the info from the
NAR that getBuildOutput() needs. */
auto source2 = sinkToSource([&](Sink & sink)
{
/* Note: we should only send the command to dump the store
path to the remote if the NAR is actually going to get read
by the destination store, which won't happen if this path
is already valid on the destination store. Since this
lambda function only gets executed if someone tries to read
from source2, we will send the command from here rather
than outside the lambda. */
conn.to << ServeProto::Command::DumpStorePath << localStore.printStorePath(info.path);
conn.to.flush();
TeeSource tee(conn.from, sink);
extractNarData(tee, localStore.printStorePath(info.path), narMembers);
});
destStore.addToStore(info, *source2, NoRepair, NoCheckSigs);
}
static void copyPathsFromRemote(
::Machine::Connection & conn,
NarMemberDatas & narMembers,
Store & localStore,
Store & destStore,
const std::map<StorePath, UnkeyedValidPathInfo> & infos
)
{
auto pathsSorted = reverseTopoSortPaths(infos);
for (auto & path : pathsSorted) {
auto & info = infos.find(path)->second;
copyPathFromRemote(
conn, narMembers, localStore, destStore,
ValidPathInfo { path, info });
}
}
} }
/* using namespace nix::build_remote; */ /* using namespace nix::build_remote; */
@@ -404,30 +253,39 @@ void State::buildRemote(ref<Store> destStore,
updateStep(ssConnecting); updateStep(ssConnecting);
auto storeRef = machine->completeStoreReference();
auto * pSpecified = std::get_if<StoreReference::Specified>(&storeRef.variant);
if (!pSpecified || pSpecified->scheme != "ssh") {
throw Error("Currently, only (legacy-)ssh stores are supported!");
}
LegacySSHStoreConfig storeConfig {
pSpecified->scheme,
pSpecified->authority,
storeRef.params
};
auto master = storeConfig.createSSHMaster(
false, // no SSH master yet
logFD.get());
// FIXME: rewrite to use Store. // FIXME: rewrite to use Store.
auto child = build_remote::openConnection(machine, master); ::Machine::Connection conn {
.machine = machine,
.store = [&]{
auto * pSpecified = std::get_if<StoreReference::Specified>(&machine->storeUri.variant);
if (!pSpecified || pSpecified->scheme != "ssh") {
throw Error("Currently, only (legacy-)ssh stores are supported!");
}
auto remoteStore = machine->openStore().dynamic_pointer_cast<LegacySSHStore>();
assert(remoteStore);
remoteStore->connPipeSize = 1024 * 1024;
if (machine->isLocalhost()) {
auto rp_new = remoteStore->remoteProgram.get();
rp_new.push_back("--builders");
rp_new.push_back("");
const_cast<nix::Setting<Strings> &>(remoteStore->remoteProgram).assign(rp_new);
}
remoteStore->extraSshArgs = {
"-a", "-oBatchMode=yes", "-oConnectTimeout=60", "-oTCPKeepAlive=yes"
};
const_cast<nix::Setting<int> &>(remoteStore->logFD).assign(logFD.get());
return nix::ref{remoteStore};
}(),
};
{ {
auto activeStepState(activeStep->state_.lock()); auto activeStepState(activeStep->state_.lock());
if (activeStepState->cancelled) throw Error("step cancelled"); if (activeStepState->cancelled) throw Error("step cancelled");
activeStepState->pid = child->sshPid; activeStepState->pid = conn.store->getConnectionPid();
} }
Finally clearPid([&]() { Finally clearPid([&]() {
@@ -442,35 +300,12 @@ void State::buildRemote(ref<Store> destStore,
process. Meh. */ process. Meh. */
}); });
::Machine::Connection conn {
{
.to = child->in.get(),
.from = child->out.get(),
/* Handshake. */
.remoteVersion = 0xdadbeef, // FIXME avoid dummy initialize
},
/*.machine =*/ machine,
};
Finally updateStats([&]() { Finally updateStats([&]() {
bytesReceived += conn.from.read; auto stats = conn.store->getConnectionStats();
bytesSent += conn.to.written; bytesReceived += stats.bytesReceived;
bytesSent += stats.bytesSent;
}); });
constexpr ServeProto::Version our_version = 0x206;
try {
conn.remoteVersion = decltype(conn)::handshake(
conn.to,
conn.from,
our_version,
machine->storeUri.render());
} catch (EndOfFile & e) {
child->sshPid.wait();
std::string s = chomp(readFile(result.logFile));
throw Error("cannot connect to %1%: %2%", machine->storeUri.render(), s);
}
{ {
auto info(machine->state->connectInfo.lock()); auto info(machine->state->connectInfo.lock());
info->consecutiveFailures = 0; info->consecutiveFailures = 0;
@@ -539,21 +374,12 @@ void State::buildRemote(ref<Store> destStore,
auto now1 = std::chrono::steady_clock::now(); auto now1 = std::chrono::steady_clock::now();
auto infos = conn.queryPathInfos(*localStore, outputs);
size_t totalNarSize = 0;
for (auto & [_, info] : infos) totalNarSize += info.narSize;
if (totalNarSize > maxOutputSize) {
result.stepStatus = bsNarSizeLimitExceeded;
return;
}
/* Copy each path. */ /* Copy each path. */
printMsg(lvlDebug, "copying outputs of %s from %s (%d bytes)", printMsg(lvlDebug, "copying outputs of %s from %s",
localStore->printStorePath(step->drvPath), machine->storeUri.render(), totalNarSize); localStore->printStorePath(step->drvPath), machine->storeUri.render());
copyClosure(*conn.store, *destStore, outputs);
build_remote::copyPathsFromRemote(conn, narMembers, *localStore, *destStore, infos);
auto now2 = std::chrono::steady_clock::now(); auto now2 = std::chrono::steady_clock::now();
result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count(); result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
@@ -574,9 +400,11 @@ void State::buildRemote(ref<Store> destStore,
} }
} }
/* Shut down the connection. */ /* Shut down the connection done by RAII.
child->in = -1;
child->sshPid.wait(); Only difference is kill() instead of wait() (i.e. send signal
then wait())
*/
} catch (Error & e) { } catch (Error & e) {
/* Disable this machine until a certain period of time has /* Disable this machine until a certain period of time has

View File

@@ -178,7 +178,7 @@ State::StepResult State::doBuildStep(nix::ref<Store> destStore,
unlink(result.logFile.c_str()); unlink(result.logFile.c_str());
} }
} catch (...) { } catch (...) {
ignoreException(); ignoreExceptionInDestructor();
} }
} }
}); });

View File

@@ -20,9 +20,7 @@
#include "store-api.hh" #include "store-api.hh"
#include "sync.hh" #include "sync.hh"
#include "nar-extractor.hh" #include "nar-extractor.hh"
#include "serve-protocol.hh" #include "legacy-ssh-store.hh"
#include "serve-protocol-impl.hh"
#include "serve-protocol-connection.hh"
#include "machines.hh" #include "machines.hh"
@@ -292,9 +290,11 @@ struct Machine : nix::Machine
bool isLocalhost() const; bool isLocalhost() const;
// A connection to a machine // A connection to a machine
struct Connection : nix::ServeProto::BasicClientConnection { struct Connection {
// Backpointer to the machine // Backpointer to the machine
ptr machine; ptr machine;
// Opened store
nix::ref<nix::LegacySSHStore> store;
}; };
}; };

View File

@@ -27,6 +27,7 @@ testenv.prepend('PERL5LIB',
separator: ':' separator: ':'
) )
testenv.prepend('PATH', testenv.prepend('PATH',
fs.parent(find_program('nix').full_path()),
fs.parent(hydra_evaluator.full_path()), fs.parent(hydra_evaluator.full_path()),
fs.parent(hydra_queue_runner.full_path()), fs.parent(hydra_queue_runner.full_path()),
meson.project_source_root() / 'src/script', meson.project_source_root() / 'src/script',