Allow the machines file to specify host public keys

It's easier for the Hydra provisioner to put host public keys in the
machines file than to separately manage the known_hosts file
(especially when the provisioner runs on a different machine).
This commit is contained in:
Eelco Dolstra 2015-08-26 13:43:02 +02:00
parent 88d7eb5247
commit 2a7fbd57cc
4 changed files with 21 additions and 10 deletions

View file

@ -10,7 +10,7 @@ AC_PROG_LN_S
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
AC_PROG_CXX AC_PROG_CXX
CXXFLAGS+=" -std=c++0x" CXXFLAGS+=" -std=c++11"
dnl Optional dependencies to build the manual, normally not needed dnl Optional dependencies to build the manual, normally not needed
dnl since the tarball comes with the PDF and HTML manuals. dnl since the tarball comes with the PDF and HTML manuals.

View file

@ -26,8 +26,7 @@ static void append(Strings & dst, const Strings & src)
} }
static void openConnection(const string & sshName, const string & sshKey, static void openConnection(Machine::ptr machine, Path tmpDir, int stderrFD, Child & child)
int stderrFD, Child & child)
{ {
Pipe to, from; Pipe to, from;
to.create(); to.create();
@ -45,11 +44,18 @@ static void openConnection(const string & sshName, const string & sshKey,
throw SysError("cannot dup stderr"); throw SysError("cannot dup stderr");
Strings argv; Strings argv;
if (sshName == "localhost") if (machine->sshName == "localhost")
argv = {"nix-store", "--serve", "--write"}; argv = {"nix-store", "--serve", "--write"};
else { else {
argv = {"ssh", sshName}; argv = {"ssh", machine->sshName};
if (sshKey != "" && sshKey != "-") append(argv, {"-i", sshKey}); if (machine->sshKey != "") append(argv, {"-i", machine->sshKey});
if (machine->sshPublicHostKey != "") {
Path fileName = tmpDir + "/host-key";
auto p = machine->sshName.find("@");
string host = p != string::npos ? string(machine->sshName, p + 1) : machine->sshName;
writeFile(fileName, host + " " + machine->sshPublicHostKey + "\n");
append(argv, {"-oUserKnownHostsFile=" + fileName});
}
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" });
@ -136,8 +142,11 @@ void State::buildRemote(std::shared_ptr<StoreAPI> store,
AutoCloseFD logFD(open(result.logFile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666)); AutoCloseFD logFD(open(result.logFile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666));
if (logFD == -1) throw SysError(format("creating log file %1%") % result.logFile); if (logFD == -1) throw SysError(format("creating log file %1%") % result.logFile);
nix::Path tmpDir = createTempDir();
AutoDelete tmpDirDel(tmpDir, true);
Child child; Child child;
openConnection(machine->sshName, machine->sshKey, logFD, child); openConnection(machine, tmpDir, logFD, child);
logFD.close(); logFD.close();
@ -277,5 +286,4 @@ void State::buildRemote(std::shared_ptr<StoreAPI> store,
/* Shut down the connection. */ /* Shut down the connection. */
child.to.close(); child.to.close();
child.pid.wait(true); child.pid.wait(true);
} }

View file

@ -40,12 +40,12 @@ void State::parseMachines(const std::string & contents)
line = trim(string(line, 0, line.find('#'))); line = trim(string(line, 0, line.find('#')));
auto tokens = tokenizeString<std::vector<std::string>>(line); auto tokens = tokenizeString<std::vector<std::string>>(line);
if (tokens.size() < 3) continue; if (tokens.size() < 3) continue;
tokens.resize(7); tokens.resize(8);
auto machine = std::make_shared<Machine>(); auto machine = std::make_shared<Machine>();
machine->sshName = tokens[0]; machine->sshName = tokens[0];
machine->systemTypes = tokenizeString<StringSet>(tokens[1], ","); machine->systemTypes = tokenizeString<StringSet>(tokens[1], ",");
machine->sshKey = tokens[2]; machine->sshKey = tokens[2] == "-" ? string("") : tokens[2];
if (tokens[3] != "") if (tokens[3] != "")
string2Int(tokens[3], machine->maxJobs); string2Int(tokens[3], machine->maxJobs);
else else
@ -57,6 +57,8 @@ void State::parseMachines(const std::string & contents)
machine->mandatoryFeatures = tokenizeString<StringSet>(tokens[6], ","); machine->mandatoryFeatures = tokenizeString<StringSet>(tokens[6], ",");
for (auto & f : machine->mandatoryFeatures) for (auto & f : machine->mandatoryFeatures)
machine->supportedFeatures.insert(f); machine->supportedFeatures.insert(f);
if (tokens[7] != "" && tokens[7] != "-")
machine->sshPublicHostKey = base64Decode(tokens[7]);
/* Re-use the State object of the previous machine with the /* Re-use the State object of the previous machine with the
same name. */ same name. */

View file

@ -205,6 +205,7 @@ struct Machine
std::set<std::string> systemTypes, supportedFeatures, mandatoryFeatures; std::set<std::string> systemTypes, supportedFeatures, mandatoryFeatures;
unsigned int maxJobs = 1; unsigned int maxJobs = 1;
float speedFactor = 1.0; float speedFactor = 1.0;
std::string sshPublicHostKey;
struct State { struct State {
typedef std::shared_ptr<State> ptr; typedef std::shared_ptr<State> ptr;