From 0f3963329018d9cf930e2a0e2b0ec2f4e26b40b3 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Fri, 2 Sep 2016 14:15:04 -0400 Subject: Factor out the unix domain socket-specific code from RemoteStore --- src/libstore/remote-store.hh | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'src/libstore/remote-store.hh') diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index e756805ea05b..a69a4f2a3b8b 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -18,7 +18,7 @@ template class Pool; /* FIXME: RemoteStore is a misnomer - should be something like DaemonStore. */ -class RemoteStore : public LocalFSStore +class RemoteStore : public virtual Store { public: @@ -26,8 +26,6 @@ public: /* Implementations of abstract store API methods. */ - std::string getUri() override; - bool isValidPathUncached(const Path & path) override; PathSet queryValidPaths(const PathSet & paths) override; @@ -84,11 +82,10 @@ public: void addSignatures(const Path & storePath, const StringSet & sigs) override; -private: +protected: struct Connection { - AutoCloseFD fd; FdSink to; FdSource from; unsigned int daemonVersion; @@ -98,11 +95,33 @@ private: void processStderr(Sink * sink = 0, Source * source = 0); }; + virtual ref openConnection() = 0; + + void setOptions(Connection & conn); + + void initConnection(Connection & conn); + +private: + ref> connections; +}; - ref openConnection(); +class UDSRemoteStore : public LocalFSStore, public RemoteStore +{ +public: + + UDSRemoteStore(const Params & params, size_t maxConnections = std::numeric_limits::max()); + + std::string getUri() override; + +private: + + struct Connection : RemoteStore::Connection + { + AutoCloseFD fd; + }; - void setOptions(ref conn); + ref openConnection() override; }; -- cgit 1.4.1 From ecba88de9367f733610121fc0153310f92e05b65 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Fri, 2 Sep 2016 14:31:38 -0400 Subject: Add ssh store implementation --- src/libstore/remote-store.hh | 8 ++-- src/libstore/ssh-store.cc | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/libstore/ssh-store.hh | 40 +++++++++++++++++++ 3 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 src/libstore/ssh-store.cc create mode 100644 src/libstore/ssh-store.hh (limited to 'src/libstore/remote-store.hh') diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index a69a4f2a3b8b..5c9c617d93e4 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -90,20 +90,20 @@ protected: FdSource from; unsigned int daemonVersion; - ~Connection(); + virtual ~Connection(); void processStderr(Sink * sink = 0, Source * source = 0); }; virtual ref openConnection() = 0; - void setOptions(Connection & conn); - void initConnection(Connection & conn); + ref> connections; + private: - ref> connections; + void setOptions(Connection & conn); }; class UDSRemoteStore : public LocalFSStore, public RemoteStore diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc new file mode 100644 index 000000000000..e1eb76659167 --- /dev/null +++ b/src/libstore/ssh-store.cc @@ -0,0 +1,92 @@ +#include "ssh-store.hh" +#include "remote-fs-accessor.hh" +#include "archive.hh" +#include "worker-protocol.hh" +#include "pool.hh" + +namespace nix { + +SSHStore::SSHStore(string uri, const Params & params, size_t maxConnections) + : Store(params) + , RemoteStore(params, maxConnections) + , tmpDir(createTempDir("", "nix", true, true, 0700)) + , socketPath((Path) tmpDir + "/ssh.sock") + , sshMaster(startProcess([&]() { + auto key = get(params, "ssh-key", ""); + if (key.empty()) + execlp("ssh", "ssh", "-N", "-M", "-S", socketPath.c_str(), uri.c_str(), NULL); + else + execlp("ssh", "ssh", "-N", "-M", "-S", socketPath.c_str(), "-i", key.c_str(), uri.c_str(), NULL); + throw SysError("starting ssh master"); + })) + , uri(std::move(uri)) +{ +} + +string SSHStore::getUri() +{ + return "ssh://" + uri; +} + +class ForwardSource : public Source +{ + Source & readSource; + Sink & writeSink; +public: + ForwardSource(Source & readSource, Sink & writeSink) : readSource(readSource), writeSink(writeSink) {} + size_t read(unsigned char * data, size_t len) override + { + auto res = readSource.read(data, len); + writeSink(data, len); + return res; + } +}; + +void SSHStore::narFromPath(const Path & path, Sink & sink) +{ + auto conn(connections->get()); + conn->to << wopNarFromPath << path; + conn->processStderr(); + ParseSink ps; + auto fwd = ForwardSource(conn->from, sink); + parseDump(ps, fwd); +} + +ref SSHStore::getFSAccessor() +{ + return make_ref(ref(shared_from_this())); +} + +ref SSHStore::openConnection() +{ + auto conn = make_ref(); + Pipe in, out; + in.create(); + out.create(); + conn->sshPid = startProcess([&]() { + if (dup2(in.readSide.get(), STDIN_FILENO) == -1) + throw SysError("duping over STDIN"); + if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) + throw SysError("duping over STDOUT"); + execlp("ssh", "ssh", "-S", socketPath.c_str(), uri.c_str(), "nix-daemon", "--stdio", NULL); + throw SysError("executing nix-daemon --stdio over ssh"); + }); + in.readSide = -1; + out.writeSide = -1; + conn->out = std::move(out.readSide); + conn->in = std::move(in.writeSide); + conn->to = FdSink(conn->in.get()); + conn->from = FdSource(conn->out.get()); + initConnection(*conn); + return conn; +} + +static RegisterStoreImplementation regStore([]( + const std::string & uri, const Store::Params & params) + -> std::shared_ptr +{ + if (std::string(uri, 0, 6) != "ssh://") return 0; + return std::make_shared(uri.substr(6), params); +}); + +} diff --git a/src/libstore/ssh-store.hh b/src/libstore/ssh-store.hh new file mode 100644 index 000000000000..44ece559853b --- /dev/null +++ b/src/libstore/ssh-store.hh @@ -0,0 +1,40 @@ +#pragma once + +#include "store-api.hh" +#include "remote-store.hh" + +namespace nix { + +class SSHStore : public RemoteStore +{ +public: + + SSHStore(string uri, const Params & params, size_t maxConnections = std::numeric_limits::max()); + + std::string getUri() override; + + void narFromPath(const Path & path, Sink & sink) override; + + ref getFSAccessor() override; + +private: + + struct Connection : RemoteStore::Connection + { + Pid sshPid; + AutoCloseFD out; + AutoCloseFD in; + }; + + ref openConnection() override; + + AutoDelete tmpDir; + + Path socketPath; + + Pid sshMaster; + + string uri; +}; + +} -- cgit 1.4.1