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);
 };
 
 

Reply via email to