Repository: mesos Updated Branches: refs/heads/master c2388a511 -> 484435384
Revert "Revert "Use the stout ELF parser to collect rootfs files."". This reverts commit 273aca1d2df1553df5fbf27c3e7479d5dc0f5dbb. Review: https://reviews.apache.org/r/56472/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/48443538 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/48443538 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/48443538 Branch: refs/heads/master Commit: 4844353847657e9449de433172905a8659033d0e Parents: 0c0080e Author: James Peach <jpe...@apache.org> Authored: Thu Feb 9 13:39:35 2017 -0800 Committer: Jiang Yan Xu <xuj...@apple.com> Committed: Thu Feb 9 13:40:51 2017 -0800 ---------------------------------------------------------------------- src/tests/containerizer/rootfs.cpp | 154 ++++++++++++++++++-------------- src/tests/containerizer/rootfs.hpp | 14 ++- 2 files changed, 100 insertions(+), 68 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/48443538/src/tests/containerizer/rootfs.cpp ---------------------------------------------------------------------- diff --git a/src/tests/containerizer/rootfs.cpp b/src/tests/containerizer/rootfs.cpp index f11f126..513c1b5 100644 --- a/src/tests/containerizer/rootfs.cpp +++ b/src/tests/containerizer/rootfs.cpp @@ -23,6 +23,15 @@ #include <stout/os.hpp> #include <stout/strings.hpp> +#include <stout/os/stat.hpp> + +#include "linux/ldd.hpp" + +using std::string; +using std::vector; + +using process::Owned; + namespace mesos { namespace internal { namespace tests { @@ -35,50 +44,71 @@ Rootfs::~Rootfs() } -Try<Nothing> Rootfs::add(const std::string& path) +Try<Nothing> Rootfs::add(const string& path) { - if (!os::exists(path)) { - return Error("File or directory not found on the host"); + Option<string> source = None(); + + // If we are copying a symlink, follow it and copy the + // target instead. While this is a little inefficient on + // disk space, it avoids complexity in dealing with chains + // of symlinks and symlinks in intermediate path components. + if (os::stat::islink(path)) { + Result<string> target = os::realpath(path); + if (target.isNone()) { + return Error("Failed to resolve '" + path + "'"); + } + + if (target.isError()) { + return Error("Failed to resolve '" + path + "': " + target.error()); + } + + source = target.get(); } - if (!strings::startsWith(path, "/")) { - return Error("Not an absolute path"); + Try<Nothing> copy = copyPath(source.isSome() ? source.get() : path, path); + if (copy.isError()) { + return Error("Failed to copy '" + path + "' to rootfs: " + copy.error()); } - std::string dirname = Path(path).dirname(); - std::string target = path::join(root, dirname); + return Nothing(); +} - if (!os::exists(target)) { - Try<Nothing> mkdir = os::mkdir(target); + +Try<Nothing> Rootfs::copyPath(const string& source, const string& destination) +{ + if (!os::exists(source)) { + return Error("'" + source + "' not found"); + } + + if (!strings::startsWith(source, "/")) { + return Error("'" + source + "' is not an absolute path"); + } + + string rootfsDestination = path::join(root, destination); + string rootfsDirectory = Path(rootfsDestination).dirname(); + + if (!os::exists(rootfsDirectory)) { + Try<Nothing> mkdir = os::mkdir(rootfsDirectory); if (mkdir.isError()) { - return Error("Failed to create directory in rootfs: " + - mkdir.error()); + return Error( + "Failed to create directory '" + rootfsDirectory + + "': " + mkdir.error()); } } - // TODO(jieyu): Make sure 'path' is not under 'root'. - - // Copy the files. We perserve all attributes so that e.g., `ping` + // Copy the files. We preserve all attributes so that e.g., `ping` // keeps its file-based capabilities. - if (os::stat::isdir(path)) { - if (os::system(strings::format( - "cp -r --preserve=all '%s' '%s'", - path, target).get()) != 0) { - return ErrnoError("Failed to copy '" + path + "' to rootfs"); - } - } else { - if (os::system(strings::format( - "cp --preserve=all '%s' '%s'", - path, target).get()) != 0) { - return ErrnoError("Failed to copy '" + path + "' to rootfs"); - } + if (os::spawn( + "cp", + {"cp", "-r", "--preserve=all", source, rootfsDestination}) != 0) { + return Error("Failed to copy '" + source + "' to rootfs"); } return Nothing(); } -Try<process::Owned<Rootfs>> LinuxRootfs::create(const std::string& root) +Try<process::Owned<Rootfs>> LinuxRootfs::create(const string& root) { process::Owned<Rootfs> rootfs(new LinuxRootfs(root)); @@ -89,64 +119,56 @@ Try<process::Owned<Rootfs>> LinuxRootfs::create(const std::string& root) } } - std::vector<std::string> files = { + Try<vector<ldcache::Entry>> cache = ldcache::parse(); + + if (cache.isError()) { + return Error("Failed to parse ld.so cache: " + cache.error()); + } + + const std::vector<string> programs = { "/bin/echo", "/bin/ls", "/bin/ping", "/bin/sh", "/bin/sleep", - "/usr/bin/sh", - "/lib/x86_64-linux-gnu", - "/lib64/ld-linux-x86-64.so.2", - "/lib64/libc.so.6", - "/lib64/libdl.so.2", - "/lib64/libidn.so.11", - "/lib64/libtinfo.so.5", - "/lib64/libselinux.so.1", - "/lib64/libpcre.so.1", - "/lib64/liblzma.so.5", - "/lib64/libpthread.so.0", - "/lib64/libcap.so.2", - "/lib64/libacl.so.1", - "/lib64/libattr.so.1", - "/lib64/librt.so.1", + }; + + hashset<string> files = { "/etc/passwd" }; - foreach (const std::string& file, files) { - // Some linux distros are moving all binaries and libraries to - // /usr, in which case /bin, /lib, and /lib64 will be symlinks - // to their equivalent directories in /usr. - Result<std::string> realpath = os::realpath(file); - if (realpath.isSome()) { - Try<Nothing> result = rootfs->add(realpath.get()); - if (result.isError()) { - return Error("Failed to add '" + realpath.get() + - "' to rootfs: " + result.error()); - } - - if (file != realpath.get()) { - result = rootfs->add(file); - if (result.isError()) { - return Error("Failed to add '" + file + "' to rootfs: " + - result.error()); - } - } + foreach (const string& program, programs) { + Try<hashset<string>> dependencies = ldd(program, cache.get()); + if (dependencies.isError()) { + return Error( + "Failed to find dependencies for '" + program + "': " + + dependencies.error()); + } + + files |= dependencies.get(); + files.insert(program); + } + + foreach (const string& file, files) { + Try<Nothing> result = rootfs->add(file); + if (result.isError()) { + return Error(result.error()); } } - std::vector<std::string> directories = { + const std::vector<string> directories = { "/proc", "/sys", "/dev", "/tmp" }; - foreach (const std::string& directory, directories) { + foreach (const string& directory, directories) { Try<Nothing> mkdir = os::mkdir(path::join(root, directory)); if (mkdir.isError()) { - return Error("Failed to create '" + directory + - "' in rootfs: " + mkdir.error()); + return Error( + "Failed to create '" + directory + "' in rootfs: " + + mkdir.error()); } } http://git-wip-us.apache.org/repos/asf/mesos/blob/48443538/src/tests/containerizer/rootfs.hpp ---------------------------------------------------------------------- diff --git a/src/tests/containerizer/rootfs.hpp b/src/tests/containerizer/rootfs.hpp index 9648638..8835a92 100644 --- a/src/tests/containerizer/rootfs.hpp +++ b/src/tests/containerizer/rootfs.hpp @@ -17,6 +17,10 @@ #ifndef __TEST_ROOTFS_HPP__ #define __TEST_ROOTFS_HPP__ +#ifndef __linux__ +#error "tests/containerizer/rootfs.hpp is only available on Linux systems" +#endif + #include <string> #include <process/owned.hpp> @@ -32,14 +36,20 @@ class Rootfs { public: virtual ~Rootfs(); - // Add a host directory or file to the root filesystem. Note that - // the host directory or file needs to be an absolute path. + // Add a host path to the root filesystem. If the given + // host path is a symlink, both the link target and the + // link itself will be copied into the root. Try<Nothing> add(const std::string& path); const std::string root; protected: Rootfs(const std::string& _root) : root(_root) {} + +private: + Try<Nothing> copyPath( + const std::string& source, + const std::string& destination); };