This is an automated email from the ASF dual-hosted git repository.

jpeach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git


The following commit(s) were added to refs/heads/master by this push:
     new 4708c2a  Added filesystem operations to the `ContainerLaunchInfo` 
message.
4708c2a is described below

commit 4708c2a368e12a89669135f47777d0dd05d9b0b2
Author: James Peach <[email protected]>
AuthorDate: Mon May 27 16:44:58 2019 -0700

    Added filesystem operations to the `ContainerLaunchInfo` message.
    
    The `filesystem/linux` isolator was using pre-exec commands
    to set up Linux ABI symlinks, which is inefficient since it
    ends spawning `ln(1)` a number of times. The fix adds a new
    `ContainerFileOperation` message to the containerizer launch
    information. The containerizer executes the requested file
    operation after performing the container mounts.
    
    Review: https://reviews.apache.org/r/70712/
---
 include/mesos/slave/containerizer.proto            | 29 +++++++++++++++++++++-
 src/common/protobuf_utils.cpp                      | 15 +++++++++++
 src/common/protobuf_utils.hpp                      |  5 ++++
 .../mesos/isolators/cgroups/cgroups.cpp            | 20 ++++++---------
 .../mesos/isolators/filesystem/linux.cpp           | 10 +++-----
 src/slave/containerizer/mesos/launch.cpp           | 28 +++++++++++++++++++++
 6 files changed, 87 insertions(+), 20 deletions(-)

diff --git a/include/mesos/slave/containerizer.proto 
b/include/mesos/slave/containerizer.proto
index e992448..b2e35cb 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -193,6 +193,29 @@ message ContainerMountInfo {
 
 
 /**
+ * Describes a file operation to be applied to the container at
+ * launch time.
+ */
+message ContainerFileOperation {
+  enum Operation {
+    // Create a symlink that points to `source` at `target`.
+    SYMLINK = 1;
+  };
+
+  message Symlink {
+    optional string source = 1;
+    optional string target = 2;
+  }
+
+  optional Operation operation = 1;
+
+  oneof parameters {
+    Symlink symlink = 2;
+  }
+}
+
+
+/**
  * Protobuf returned by Isolator::prepare(). The command is executed
  * by the Launcher in the containerized context.
  * Note: Currently, any URIs or Environment in the CommandInfo will be
@@ -202,7 +225,7 @@ message ContainerMountInfo {
 message ContainerLaunchInfo {
   // The additional preparation commands to execute before
   // executing the command.
-  repeated CommandInfo pre_exec_commands = 1;
+  repeated CommandInfo pre_exec_commands = 1 [deprecated=true];
 
   // The environment set for the container.
   optional Environment environment = 2;
@@ -248,6 +271,10 @@ message ContainerLaunchInfo {
   // Paths are masked after all other mounts are made.
   repeated string masked_paths = 21;
 
+  // The list of filesystem operations to perform after the container
+  // mounts, but before launching the container process.
+  repeated ContainerFileOperation file_operations = 22;
+
   // (Linux only) The Seccomp profile for the container.
   // The profile is used to configure syscall filtering via `libseccomp`.
   optional seccomp.ContainerSeccompProfile seccomp_profile = 18;
diff --git a/src/common/protobuf_utils.cpp b/src/common/protobuf_utils.cpp
index 8b252cb..870859d 100644
--- a/src/common/protobuf_utils.cpp
+++ b/src/common/protobuf_utils.cpp
@@ -66,6 +66,7 @@ using google::protobuf::RepeatedPtrField;
 
 using mesos::authorization::VIEW_ROLE;
 
+using mesos::slave::ContainerFileOperation;
 using mesos::slave::ContainerLimitation;
 using mesos::slave::ContainerMountInfo;
 using mesos::slave::ContainerState;
@@ -1241,6 +1242,20 @@ ContainerMountInfo createContainerMount(
   return mnt;
 }
 
+
+mesos::slave::ContainerFileOperation containerSymlinkOperation(
+    const std::string& source,
+    const std::string& target)
+{
+  ContainerFileOperation op;
+
+  op.set_operation(ContainerFileOperation::SYMLINK);
+  op.mutable_symlink()->set_source(source);
+  op.mutable_symlink()->set_target(target);
+
+  return op;
+}
+
 } // namespace slave {
 
 namespace maintenance {
diff --git a/src/common/protobuf_utils.hpp b/src/common/protobuf_utils.hpp
index 273ae27..8aa9aff 100644
--- a/src/common/protobuf_utils.hpp
+++ b/src/common/protobuf_utils.hpp
@@ -414,6 +414,11 @@ mesos::slave::ContainerMountInfo createContainerMount(
     const std::string& options,
     unsigned long flags);
 
+
+mesos::slave::ContainerFileOperation containerSymlinkOperation(
+    const std::string& source,
+    const std::string& target);
+
 } // namespace slave {
 
 namespace maintenance {
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp 
b/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
index 8f94453..e7819d7 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
@@ -42,6 +42,8 @@
 #include "slave/containerizer/mesos/isolators/cgroups/cgroups.hpp"
 #include "slave/containerizer/mesos/isolators/cgroups/constants.hpp"
 
+using mesos::internal::protobuf::slave::containerSymlinkOperation;
+
 using mesos::slave::ContainerConfig;
 using mesos::slave::ContainerLaunchInfo;
 using mesos::slave::ContainerLimitation;
@@ -565,18 +567,12 @@ Future<Option<ContainerLaunchInfo>> 
CgroupsIsolatorProcess::__prepare(
   foreach (const string& hierarchy, subsystems.keys()) {
     if (subsystems.get(hierarchy).size() > 1) {
       foreach (const Owned<Subsystem>& subsystem, subsystems.get(hierarchy)) {
-        CommandInfo* command = launchInfo.add_pre_exec_commands();
-        command->set_shell(false);
-        command->set_value("ln");
-        command->add_arguments("ln");
-        command->add_arguments("-s");
-        command->add_arguments(
-            path::join("/sys/fs/cgroup", Path(hierarchy).basename()));
-
-        command->add_arguments(path::join(
-            containerConfig.rootfs(),
-            "/sys/fs/cgroup",
-            subsystem->name()));
+        *launchInfo.add_file_operations() = containerSymlinkOperation(
+            path::join("/sys/fs/cgroup", Path(hierarchy).basename()),
+            path::join(
+              containerConfig.rootfs(),
+              "/sys/fs/cgroup",
+              subsystem->name()));
       }
     }
   }
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp 
b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
index 190054c..3cfb6e9 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
@@ -61,6 +61,7 @@ using std::string;
 using std::vector;
 
 using mesos::internal::protobuf::slave::createContainerMount;
+using mesos::internal::protobuf::slave::containerSymlinkOperation;
 
 using mesos::slave::ContainerClass;
 using mesos::slave::ContainerConfig;
@@ -213,13 +214,8 @@ static Try<Nothing> makeStandardDevices(
   };
 
   foreach (const auto& symlink, symlinks) {
-    CommandInfo* ln = launchInfo.add_pre_exec_commands();
-    ln->set_shell(false);
-    ln->set_value("ln");
-    ln->add_arguments("ln");
-    ln->add_arguments("-s");
-    ln->add_arguments(symlink.first);
-    ln->add_arguments(symlink.second);
+    *launchInfo.add_file_operations() =
+      containerSymlinkOperation(symlink.first, symlink.second);
   }
 
   // TODO(idownes): Set up console device.
diff --git a/src/slave/containerizer/mesos/launch.cpp 
b/src/slave/containerizer/mesos/launch.cpp
index 5ddb4c7..0c482f4 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -33,6 +33,7 @@
 
 #include <stout/adaptor.hpp>
 #include <stout/foreach.hpp>
+#include <stout/fs.hpp>
 #include <stout/option.hpp>
 #include <stout/os.hpp>
 #include <stout/path.hpp>
@@ -94,6 +95,7 @@ using mesos::internal::capabilities::ProcessCapabilities;
 using mesos::internal::seccomp::SeccompFilter;
 #endif
 
+using mesos::slave::ContainerFileOperation;
 using mesos::slave::ContainerLaunchInfo;
 using mesos::slave::ContainerMountInfo;
 
@@ -472,6 +474,25 @@ static Try<Nothing> maskPath(const string& target)
 }
 
 
+static Try<Nothing> executeFileOperation(const ContainerFileOperation& op)
+{
+  Try<Nothing> result = Nothing();
+
+  switch (op.operation()) {
+    case ContainerFileOperation::SYMLINK:
+      result = ::fs::symlink(op.symlink().source(), op.symlink().target());
+      if (result.isError()) {
+        return Error(
+            "Failed to link '" + op.symlink().source() + "' as '" +
+            op.symlink().target() + "': " + result.error());
+      }
+      break;
+  }
+
+  return result;
+}
+
+
 static Try<Nothing> installResourceLimits(const RLimitInfo& limits)
 {
 #ifdef __WINDOWS__
@@ -768,6 +789,13 @@ int MesosContainerizerLaunch::execute()
     mount = maskPath(target);
     if (mount.isError()) {
       cerr << "Failed to mask container paths: " << mount.error() << endl;
+    }
+  }
+
+  foreach (const ContainerFileOperation& op, launchInfo.file_operations()) {
+    Try<Nothing> result = executeFileOperation(op);
+    if (result.isError()) {
+      cerr << result.error() << endl;
       exitWithStatus(EXIT_FAILURE);
     }
   }

Reply via email to