Remove $NIX_BUILD_HOOK and $NIX_CURRENT_LOAD

This is to simplify remote build configuration. These environment
variables predate nix.conf.

The build hook now has a sensible default (namely build-remote).

The current load is kept in the Nix state directory now.
This commit is contained in:
Eelco Dolstra 2017-05-01 15:46:47 +02:00
parent ca9f589a93
commit d7653dfc6d
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
6 changed files with 12 additions and 156 deletions

View file

@ -22,10 +22,7 @@ will call whenever it wants to build a derivation. The build hook
will perform it in the usual way if possible, or it can accept it, in will perform it in the usual way if possible, or it can accept it, in
which case it is responsible for somehow getting the inputs of the which case it is responsible for somehow getting the inputs of the
build to another machine, doing the build there, and getting the build to another machine, doing the build there, and getting the
results back. The details of the build hook protocol are described in results back.</para>
the documentation of the <link
linkend="envar-build-hook"><envar>NIX_BUILD_HOOK</envar>
variable</link>.</para>
<example xml:id='ex-remote-systems'><title>Remote machine configuration: <example xml:id='ex-remote-systems'><title>Remote machine configuration:
<filename>remote-systems.conf</filename></title> <filename>remote-systems.conf</filename></title>
@ -103,14 +100,6 @@ requiredSystemFeatures = [ "kvm" ];
</orderedlist> </orderedlist>
You should also set up the environment variable </para>
<envar>NIX_CURRENT_LOAD</envar> to point at a directory (e.g.,
<filename>/var/run/nix/current-load</filename>) that
<filename>build-remote</filename> uses to remember how many builds
it is currently executing remotely. It doesn't look at the actual
load on the remote machine, so if you have multiple instances of Nix
running, they should use the same <envar>NIX_CURRENT_LOAD</envar>
file. Maybe in the future <filename>build-remote</filename> will
look at the actual remote load.</para>
</chapter> </chapter>

View file

@ -148,139 +148,6 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
</varlistentry> </varlistentry>
<varlistentry xml:id="envar-build-hook"><term><envar>NIX_BUILD_HOOK</envar></term>
<listitem>
<para>Specifies the location of the <emphasis>build hook</emphasis>,
which is a program (typically some script) that Nix will call
whenever it wants to build a derivation. This is used to implement
distributed builds<phrase condition="manual"> (see <xref
linkend="chap-distributed-builds" />)</phrase>.</para>
<!--
The protocol by
which the calling Nix process and the build hook communicate is as
follows.
<para>The build hook is called with the following command-line
arguments:
<orderedlist>
<listitem><para>A boolean value <literal>0</literal> or
<literal>1</literal> specifying whether Nix can locally execute
more builds, as per the <link
linkend="opt-max-jobs"><option>- -max-jobs</option> option</link>.
The purpose of this argument is to allow the hook to not have to
maintain bookkeeping for the local machine.</para></listitem>
<listitem><para>The Nix platform identifier for the local machine
(e.g., <literal>i686-linux</literal>).</para></listitem>
<listitem><para>The Nix platform identifier for the derivation,
i.e., its <link linkend="attr-system"><varname>system</varname>
attribute</link>.</para></listitem>
<listitem><para>The store path of the derivation.</para></listitem>
</orderedlist>
</para>
<para>On the basis of this information, and whatever persistent
state the build hook keeps about other machines and their current
load, it has to decide what to do with the build. It should print
out on standard error one of the following responses (terminated by
a newline, <literal>"\n"</literal>):
<variablelist>
<varlistentry><term><literal># decline</literal></term>
<listitem><para>The build hook is not willing or able to perform
the build; the calling Nix process should do the build itself,
if possible.</para></listitem>
</varlistentry>
<varlistentry><term><literal># postpone</literal></term>
<listitem><para>The build hook cannot perform the build now, but
can do so in the future (e.g., because all available build slots
on remote machines are in use). The calling Nix process should
postpone this build until at least one currently running build
has terminated.</para></listitem>
</varlistentry>
<varlistentry><term><literal># accept</literal></term>
<listitem><para>The build hook has accepted the
build.</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>After sending <literal># accept</literal>, the hook should
read one line from standard input, which will be the string
<literal>okay</literal>. It can then proceed with the build.
Before sending <literal>okay</literal>, Nix will store in the hooks
current directory a number of text files that contain information
about the derivation:
<variablelist>
<varlistentry><term><filename>inputs</filename></term>
<listitem><para>The set of store paths that are inputs to the
build process (one per line). These have to be copied
<emphasis>to</emphasis> the remote machine (in addition to the
store derivation itself).</para></listitem>
</varlistentry>
<varlistentry><term><filename>outputs</filename></term>
<listitem><para>The set of store paths that are outputs of the
derivation (one per line). These have to be copied
<emphasis>from</emphasis> the remote machine if the build
succeeds.</para></listitem>
</varlistentry>
<varlistentry><term><filename>references</filename></term>
<listitem><para>The reference graph of the inputs, in the format
accepted by the command <command>nix-store
- -register-validity</command>. It is necessary to run this
command on the remote machine after copying the inputs to inform
Nix on the remote machine that the inputs are valid
paths.</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>The hook should copy the inputs to the remote machine,
register the validity of the inputs, perform the remote build, and
copy the outputs back to the local machine. An exit code other than
<literal>0</literal> indicates that the hook has failed. An exit
code equal to 100 means that the remote build failed (as opposed to,
e.g., a network error).</para>
-->
</listitem>
</varlistentry>
<varlistentry xml:id="envar-remote"><term><envar>NIX_REMOTE</envar></term> <varlistentry xml:id="envar-remote"><term><envar>NIX_REMOTE</envar></term>
<listitem><para>This variable should be set to <listitem><para>This variable should be set to

View file

@ -140,7 +140,9 @@ int main (int argc, char * * argv)
settings.buildTimeout = std::stoll(argv[3]); settings.buildTimeout = std::stoll(argv[3]);
verbosity = (Verbosity) std::stoll(argv[4]); verbosity = (Verbosity) std::stoll(argv[4]);
currentLoad = getEnv("NIX_CURRENT_LOAD", "/run/nix/current-load"); /* It would be more appropriate to use $XDG_RUNTIME_DIR, since
that gets cleared on reboot, but it wouldn't work on OS X. */
currentLoad = settings.nixStateDir + "/current-load";
std::shared_ptr<Store> sshStore; std::shared_ptr<Store> sshStore;
AutoCloseFD bestSlotLock; AutoCloseFD bestSlotLock;

View file

@ -583,11 +583,7 @@ struct HookInstance
HookInstance::HookInstance() HookInstance::HookInstance()
{ {
debug("starting build hook"); debug("starting build hook %s", settings.buildHook);
Path buildHook = getEnv("NIX_BUILD_HOOK");
if (string(buildHook, 0, 1) != "/") buildHook = settings.nixLibexecDir + "/nix/" + buildHook;
buildHook = canonPath(buildHook);
/* Create a pipe to get the output of the child. */ /* Create a pipe to get the output of the child. */
fromHook.create(); fromHook.create();
@ -621,9 +617,9 @@ HookInstance::HookInstance()
std::to_string(verbosity) std::to_string(verbosity)
}; };
execv(buildHook.c_str(), stringsToCharPtrs(args).data()); execv(settings.buildHook.get().c_str(), stringsToCharPtrs(args).data());
throw SysError(format("executing %1%") % buildHook); throw SysError("executing %s", settings.buildHook);
}); });
pid.setSeparatePG(true); pid.setSeparatePG(true);
@ -1569,7 +1565,7 @@ void DerivationGoal::buildDone()
HookReply DerivationGoal::tryBuildHook() HookReply DerivationGoal::tryBuildHook()
{ {
if (!settings.useBuildHook || getEnv("NIX_BUILD_HOOK") == "" || !useDerivation) return rpDecline; if (!settings.useBuildHook || !useDerivation) return rpDecline;
if (!worker.hook) if (!worker.hook)
worker.hook = std::make_unique<HookInstance>(); worker.hook = std::make_unique<HookInstance>();

View file

@ -127,6 +127,9 @@ public:
Setting<bool> useBuildHook{this, true, "remote-builds", Setting<bool> useBuildHook{this, true, "remote-builds",
"Whether to use build hooks (for distributed builds)."}; "Whether to use build hooks (for distributed builds)."};
PathSetting buildHook{this, true, nixLibexecDir + "/nix/build-remote", "build-hook",
"The path of the helper program that executes builds to remote machines."};
Setting<off_t> reservedSize{this, 8 * 1024 * 1024, "gc-reserved-space", Setting<off_t> reservedSize{this, 8 * 1024 * 1024, "gc-reserved-space",
"Amount of reserved disk space for the garbage collector."}; "Amount of reserved disk space for the garbage collector."};

View file

@ -43,7 +43,6 @@ in
{ config, pkgs, ... }: { config, pkgs, ... }:
{ nix.maxJobs = 0; # force remote building { nix.maxJobs = 0; # force remote building
nix.distributedBuilds = true; nix.distributedBuilds = true;
nix.envVars = pkgs.lib.mkAfter { NIX_BUILD_HOOK = "${nix}/libexec/nix/build-remote"; };
nix.buildMachines = nix.buildMachines =
[ { hostName = "slave1"; [ { hostName = "slave1";
sshUser = "root"; sshUser = "root";